0 前言
??
這兩年開(kāi)始畢業(yè)設(shè)計(jì)和畢業(yè)答辯的要求和難度不斷提升,傳統(tǒng)的畢設(shè)題目缺少創(chuàng)新和亮點(diǎn),往往達(dá)不到畢業(yè)答辯的要求,這兩年不斷有學(xué)弟學(xué)妹告訴學(xué)長(zhǎng)自己做的項(xiàng)目系統(tǒng)達(dá)不到老師的要求。
為了大家能夠順利以及最少的精力通過(guò)畢設(shè),學(xué)長(zhǎng)分享優(yōu)質(zhì)畢業(yè)設(shè)計(jì)項(xiàng)目,今天要分享的是
?? 畢業(yè)設(shè)計(jì) 基于51單片機(jī)的汽車(chē)倒車(chē)防撞報(bào)警系統(tǒng) (源碼+硬件+論文)
??學(xué)長(zhǎng)這里給一個(gè)題目綜合評(píng)分(每項(xiàng)滿(mǎn)分5分)
- 難度系數(shù):3分
- 工作量:3分
- 創(chuàng)新點(diǎn):4分
?? 項(xiàng)目分享:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-492398.html
https://gitee.com/sinonfin/sharing文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-492398.html
1 主要功能
系統(tǒng)硬件結(jié)構(gòu)框圖,主要為STC89C52單片機(jī)最小系統(tǒng),LCD1602顯示器集成電路,HC-SR04超聲波測(cè)距模塊,蜂鳴器報(bào)警集成電路和按鍵電路。由圖1-1可確定其功能模塊的具體設(shè)計(jì)情況與邏輯關(guān)聯(lián)。
接入5V直流穩(wěn)壓電流,按動(dòng)自鎖按鈕給硬件系統(tǒng)上電,首先由超聲波測(cè)距模塊測(cè)量距離,單片機(jī)將所測(cè)的距離數(shù)值處理之后顯示在LCD1602上。利用按鍵裝置調(diào)整報(bào)警距離上限,若測(cè)量距離小于預(yù)先設(shè)定值,蜂鳴器發(fā)聲報(bào)警、LED燈閃爍。
2 硬件設(shè)計(jì)(原理圖)
3 核心軟件設(shè)計(jì)
由上文分析論述可知,超聲波傳感器基于超聲波傳播與返回時(shí)間實(shí)現(xiàn)距離測(cè)定功能。在明確時(shí)間數(shù)據(jù)的基礎(chǔ)上,結(jié)合超聲波在空氣中的傳播速度對(duì)距離參數(shù)進(jìn)行計(jì)算。其具體的技術(shù)原理詳見(jiàn)圖2-8所示。實(shí)現(xiàn)思路:第一種,直接給trig高電平,然后讀取ECHO引腳是否為高電平,若為高電平,則開(kāi)啟定時(shí)器,然后繼續(xù)檢測(cè)等待其為低電平的時(shí)候,獲取計(jì)數(shù)器值,然后進(jìn)行計(jì)算。第二種,開(kāi)啟外部中斷,先將ECHO配置上升沿中斷,當(dāng)中斷來(lái)臨的時(shí)候,在中斷函數(shù)里面開(kāi)啟定時(shí)器,再將其配置為下降沿中斷,等待下降沿中斷來(lái)臨的時(shí)候,獲取計(jì)數(shù)器值。
其實(shí)上面的兩種方法,其思路都是通過(guò)計(jì)算定時(shí)器的counter值,來(lái)計(jì)算距離。
第三種是讓定時(shí)器一路PWM控制觸發(fā)以及觸發(fā)周期,超聲波返回信號(hào)高電平時(shí)間用定時(shí)器通道捕捉功能獲取。
基于上述工作原理,超聲波將由發(fā)射裝置發(fā)出長(zhǎng)約6mm和頻率為40kHz的超聲波信號(hào)并經(jīng)目標(biāo)對(duì)象反射之后返回至傳感器接收裝置進(jìn)行識(shí)別和確定,在此基礎(chǔ)上可確定超聲波往返一次所需時(shí)間。該時(shí)間的1/2即超聲波在傳感器與目標(biāo)對(duì)象之間的傳播時(shí)間,進(jìn)而可計(jì)算相應(yīng)的距離數(shù)據(jù)。
主程序具體負(fù)責(zé)相關(guān)數(shù)據(jù)的處理和分析工作,并為各個(gè)功能模塊的正常運(yùn)行提供必要的程序指令支持和保障。該程序的技術(shù)流程詳見(jiàn)圖
關(guān)鍵代碼
#include <reg52.h>
#include <intrins.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
sfr ISP_DATA = 0xe2;
sfr ISP_ADDRH = 0xe3;
sfr ISP_ADDRL = 0xe4;
sfr ISP_CMD = 0xe5;
sfr ISP_TRIG = 0xe6;
sfr ISP_CONTR = 0xe7;
sbit LcdRs_P = P2^7;
sbit LcdRw_P = P2^6;
sbit LcdEn_P = P2^5;
sbit Trig_P = P2^2;
sbit Echo_P = P2^3;
sbit KeySet_P = P3^2;
sbit KeyDown_P = P3^3;
sbit KeyUp_P = P3^4;
sbit Buzzer_P = P2^1;
sbit Led_P = P2^0;
uint gAlarm;
// 單片機(jī)內(nèi)部EEPROM不使能
void ISP_Disable()
{
ISP_CONTR = 0;
ISP_ADDRH = 0;
ISP_ADDRL = 0;
}
// 從單片機(jī)內(nèi)部EEPROM讀一個(gè)字節(jié),從0x2000地址開(kāi)始
unsigned char EEPROM_Read(unsigned int add)
{
ISP_DATA = 0x00;
ISP_CONTR = 0x83;
ISP_CMD = 0x01;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
// 對(duì)STC89C51系列來(lái)說(shuō),每次要寫(xiě)入0x46,再寫(xiě)入0xB9,ISP/IAP才會(huì)生效
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
_nop_();
ISP_Disable();
return (ISP_DATA);
}
// 往單片機(jī)內(nèi)部EEPROM寫(xiě)一個(gè)字節(jié),從0x2000地址開(kāi)始
void EEPROM_Write(unsigned int add,unsigned char ch)
{
ISP_CONTR = 0x83;
ISP_CMD = 0x02;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
ISP_DATA = ch;
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
_nop_();
ISP_Disable();
}
// 擦除單片機(jī)內(nèi)部EEPROM的一個(gè)扇區(qū)
// 寫(xiě)8個(gè)扇區(qū)中隨便一個(gè)的地址,便擦除該扇區(qū),寫(xiě)入前要先擦除
void Sector_Erase(unsigned int add)
{
ISP_CONTR = 0x83;
ISP_CMD = 0x03;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
_nop_();
ISP_Disable();
}
// 毫秒級(jí)的延時(shí)函數(shù),time是要延時(shí)的毫秒數(shù)
void DelayMs(uint time)
{
uint i,j;
for(i=0;i<time;i++)
for(j=0;j<112;j++);
}
// 1602液晶寫(xiě)命令函數(shù),cmd就是要寫(xiě)入的命令
void LcdWriteCmd(uchar cmd)
{
LcdRs_P = 0;
LcdRw_P = 0;
LcdEn_P = 0;
P0=cmd;
DelayMs(2);
LcdEn_P = 1;
DelayMs(2);
LcdEn_P = 0;
}
// 1602液晶寫(xiě)數(shù)據(jù)函數(shù),dat就是要寫(xiě)入的命令
void LcdWriteData(uchar dat)
{
LcdRs_P = 1;
LcdRw_P = 0;
LcdEn_P = 0;
P0=dat;
DelayMs(2);
LcdEn_P = 1;
DelayMs(2);
LcdEn_P = 0;
}
// 1602液晶初始化函數(shù)
void LcdInit()
{
LcdWriteCmd(0x38); // 16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)口
LcdWriteCmd(0x0C); // 開(kāi)顯示,不顯示光標(biāo)
LcdWriteCmd(0x06); // 地址加1,當(dāng)寫(xiě)入數(shù)據(jù)后光標(biāo)右移
LcdWriteCmd(0x01); // 清屏
}
// 液晶光標(biāo)定位函數(shù)
void LcdGotoXY(uchar line,uchar column)
{
// 第一行
if(line==0)
LcdWriteCmd(0x80+column);
// 第二行
if(line==1)
LcdWriteCmd(0x80+0x40+column);
}
// 液晶輸出字符串函數(shù)
void LcdPrintStr(uchar *str)
{
while(*str!='\0')
LcdWriteData(*str++);
}
// 液晶輸出數(shù)字
void LcdPrintNum(uint num)
{
LcdWriteData(num/100+0x30); // 百位
LcdWriteData(num%100/10+0x30); // 十位
LcdWriteData(num%10+0x30); // 個(gè)位
}
// 計(jì)算測(cè)到的距離
uint GetDistance(void)
{
uint ss; // 用于記錄測(cè)得的距離
TH0=0;
TL0=0;
Trig_P=1; // 給超聲波模塊一個(gè)開(kāi)始脈沖
DelayMs(1);
Trig_P=0;
while(!Echo_P);
TR0=1;
while(Echo_P);
TR0=0;
ss=((TH0*256+TL0)*0.034)/2; // 距離cm=(時(shí)間us * 速度cm/us)/2
return ss;
}
// 按鍵掃描
void KeyScanf()
{
uchar i;
uchar dat1,dat2;
if(KeySet_P==0) // 判斷是否有按鍵按下
{
DelayMs(10); // 消除按鍵按下的抖動(dòng)
while(!KeySet_P); // 等待按鍵釋放
DelayMs(10); // 消除按鍵松開(kāi)的抖動(dòng)
LcdGotoXY(1,2); // 液晶第二行刷新顯示
LcdPrintStr("alarm= cm");
LcdGotoXY(1,8);
LcdPrintNum(gAlarm);
i=1;
while(i)
{
if(KeyDown_P==0) // 報(bào)警值減的處理
{
DelayMs(300);
if(gAlarm>2)
gAlarm--;
LcdGotoXY(1,8);
LcdPrintNum(gAlarm);
}
if(KeyUp_P==0) // 報(bào)警值加的處理
{
DelayMs(300);
if(gAlarm<400)
gAlarm++;
LcdGotoXY(1,8);
LcdPrintNum(gAlarm);
}
if(KeySet_P==0) // 再次按下設(shè)置鍵的判斷
{
DelayMs(10);
while(!KeySet_P);
DelayMs(10);
LcdGotoXY(1,0);
LcdPrintStr(" S= cm ");
i=0;
}
}
dat1=gAlarm/100;
dat2=gAlarm%100;
Sector_Erase(0x2000);
EEPROM_Write(0x2000,dat1);
EEPROM_Write(0x2001,dat2);
}
}
// 報(bào)警判斷
void AlarmJudge(uint ss)
{
uchar i;
float alr1,alr2,alr3,alr4;
alr1=gAlarm/4.00*1;
alr2=gAlarm/4.00*2;
alr3=gAlarm/4.00*3;
alr4=gAlarm/4.00*4;
// 報(bào)警頻率最快
if(ss<alr1)
{
for(i=0;i<10;i++)
{
Led_P=0;
Buzzer_P=0;
DelayMs(50);
Led_P=1;
Buzzer_P=1;
DelayMs(50);
KeyScanf();
}
}
// 報(bào)警頻率第二快
else if(ss<alr2)
{
for(i=0;i<5;i++)
{
Led_P=0;
Buzzer_P=0;
DelayMs(100);
Led_P=1;
Buzzer_P=1;
DelayMs(100);
KeyScanf();
}
}
// 報(bào)警頻率第三快
else if(ss<alr3)
{
for(i=0;i<2;i++)
{
Led_P=0;
Buzzer_P=0;
DelayMs(200);
Led_P=1;
Buzzer_P=1;
DelayMs(200);
KeyScanf();
}
}
// 報(bào)警頻率最慢
else if(ss<alr4)
{
for(i=0;i<2;i++)
{
Led_P=0;
Buzzer_P=0;
DelayMs(300);
Led_P=1;
Buzzer_P=1;
DelayMs(300);
KeyScanf();
}
}
// 不報(bào)警
else
{
Led_P=1;
Buzzer_P=1;
for(i=0;i<100;i++)
{
KeyScanf();
DelayMs(10);
}
}
}
bit busy = 0;
void Uart_Isr() interrupt 4 using 1
{
if (RI)
{
RI = 0; //Clear receive interrupt flag
}
// if (TI)
// {
// TI = 0; //Clear transmit interrupt flag
// busy = 0; //Clear transmit busy flag
// }
}
void Delay150us() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 2;
j = 153;
do
{
while (--j);
} while (--i);
}
/*----------------------------
Send a byte data to UART
Input: dat (data to be sent)
Output:None
----------------------------*/
void SendData(unsigned char dat)
{
// while (busy); //Wait for the completion of the previous data is sent
// ACC = dat; //
// busy = 1;
// TI = 0;
SBUF = dat; //Send data to UART buffer
//Delay150us();
while(!TI);
TI = 0;
}
/*----------------------------
Send a string to UART
Input: s (address of string)
Output:None
----------------------------*/
void SendString(char *s)
{
while (*s) //Check the end of the string
{
SendData(*s++); //Send current char and increment string ptr
}
}
#define FOSC 11059200L //System frequency
#define BAUD 9600 //UART baudrate
volatile unsigned char Dat[16];
// 主函數(shù)
void main()
{
uchar dat1,dat2;
uint dist;
unsigned short Cnt = 0;
LcdInit(); // 執(zhí)行液晶初始化
TMOD = 0x01; // 選擇定時(shí)器0,并且確定是工作方式1(為了超聲波模塊測(cè)量距離計(jì)時(shí)用的)
LcdGotoXY(0,0); // 定位到第0行第0列
LcdPrintStr(" HC-SR04 System "); // 第0行顯示“HC-SR04 System”
LcdGotoXY(1,0); // 定位到第1行第0列
LcdPrintStr(" S= cm "); // 第1行顯示“S= cm”
dat1=EEPROM_Read(0x2000); // 從EEPROM讀取報(bào)警值
dat2=EEPROM_Read(0x2001);
gAlarm=dat1*100+dat2;
if((gAlarm==0)||(gAlarm>400)) // 如果讀取到的報(bào)警值異常
{
gAlarm=25; // 重新賦值報(bào)警值為25
}
// SCON = 0x50;
// TL2 = RCAP2L = (65536-(FOSC/32/BAUD)); //Set auto-reload vaule
// TH2 = RCAP2H = (65536-(FOSC/32/BAUD)) >> 8;
// T2CON = 0x34; //Timer2 start run
// ES = 0; //Enable UART interrupt
// EA =1;
//
//PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位數(shù)據(jù),可變波特率
//AUXR &= 0xBF; //定時(shí)器1時(shí)鐘為Fosc/12,即12T
//AUXR &= 0xFE; //串口1選擇定時(shí)器1為波特率發(fā)生器
TMOD &= 0x0F; //清除定時(shí)器1模式位
TMOD |= 0x20; //設(shè)定定時(shí)器1為8位自動(dòng)重裝方式
TL1 = 0xFD; //設(shè)定定時(shí)初值
TH1 = 0xFD; //設(shè)定定時(shí)器重裝值
ET1 = 0; //禁止定時(shí)器1中斷
TR1 = 1; //啟動(dòng)定時(shí)器1
//SendData(0XA5);
while(1)
{
dist=GetDistance(); // 通過(guò)超聲波模塊獲取距離
LcdGotoXY(1,7); // 定位到第1行第7列
LcdPrintNum(dist); // 將獲取到的距離在液晶上面顯示
if(++Cnt>=1)
{
Cnt = 0;
sprintf(Dat,"S=%d cm\r\n",(uint) dist);
SendString(Dat);
}
AlarmJudge(dist);
}
}
4 實(shí)現(xiàn)效果
5 最后
包含內(nèi)容
?? 項(xiàng)目分享:
https://gitee.com/sinonfin/sharing
到了這里,關(guān)于畢業(yè)設(shè)計(jì) 基于51單片機(jī)的汽車(chē)倒車(chē)防撞報(bào)警系統(tǒng) (源碼+硬件+論文)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!