找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 3503|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

單片機(jī)小車超聲波防撞倒車?yán)走_(dá)系統(tǒng)Proteus仿真程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:981337 發(fā)表于 2021-11-17 20:38 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
防倒車?yán)走_(dá)系統(tǒng)自己的一點(diǎn)思考
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機(jī)源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>

  3. #define uchar unsigned char        // 以后unsigned char就可以用uchar代替
  4. #define uint  unsigned int        // 以后unsigned int 就可以用uint 代替

  5. sfr ISP_DATA  = 0xe2;                        // 數(shù)據(jù)寄存器
  6. sfr ISP_ADDRH = 0xe3;                        // 地址寄存器高八位
  7. sfr ISP_ADDRL = 0xe4;                        // 地址寄存器低八位
  8. sfr ISP_CMD   = 0xe5;                        // 命令寄存器
  9. sfr ISP_TRIG  = 0xe6;                        // 命令觸發(fā)寄存器
  10. sfr ISP_CONTR = 0xe7;                        // 命令寄存器

  11. sbit LcdRs_P   = P1^1;                // 1602液晶的RS管腳      
  12. sbit LcdRw_P   = P1^2;                // 1602液晶的RW管腳
  13. sbit LcdEn_P   = P1^3;                // 1602液晶的EN管腳

  14. sbit Trig1_P   = P3^2;                // 超聲波模塊1的Trig管腳
  15. sbit Echo1_P   = P3^3;                // 超聲波模塊1的Echo管腳

  16. sbit KeySet_P  = P2^2;                // 設(shè)置按鍵的管腳
  17. sbit KeyDown_P = P2^1;                // 減按鍵的管腳
  18. sbit KeyUp_P   = P2^0;                // 加按鍵的管腳

  19. sbit Buzzer_P  = P2^3;                // 蜂鳴器的管腳
  20. sbit Led1_P    = P3^4;                // 傳感器1報(bào)警燈

  21. uint gAlarm;                                                        // 報(bào)警距離變量



  22. /*********************************************************/
  23. // 單片機(jī)內(nèi)部EEPROM不使能
  24. /*********************************************************/
  25. void ISP_Disable()
  26. {
  27.         ISP_CONTR = 0;
  28.         ISP_ADDRH = 0;
  29.         ISP_ADDRL = 0;
  30. }


  31. /*********************************************************/
  32. // 從單片機(jī)內(nèi)部EEPROM讀一個(gè)字節(jié),從0x2000地址開(kāi)始
  33. /*********************************************************/
  34. unsigned char EEPROM_Read(unsigned int add)
  35. {
  36.         ISP_DATA  = 0x00;
  37.         ISP_CONTR = 0x83;
  38.         ISP_CMD   = 0x01;
  39.         ISP_ADDRH = (unsigned char)(add>>8);
  40.         ISP_ADDRL = (unsigned char)(add&0xff);
  41.         // 對(duì)STC89C51系列來(lái)說(shuō),每次要寫入0x46,再寫入0xB9,ISP/IAP才會(huì)生效
  42.         ISP_TRIG  = 0x46;          
  43.         ISP_TRIG  = 0xB9;
  44.         _nop_();
  45.         ISP_Disable();
  46.         return (ISP_DATA);
  47. }


  48. /*********************************************************/
  49. // 往單片機(jī)內(nèi)部EEPROM寫一個(gè)字節(jié),從0x2000地址開(kāi)始
  50. /*********************************************************/
  51. void EEPROM_Write(unsigned int add,unsigned char ch)
  52. {
  53.         ISP_CONTR = 0x83;
  54.         ISP_CMD   = 0x02;
  55.         ISP_ADDRH = (unsigned char)(add>>8);
  56.         ISP_ADDRL = (unsigned char)(add&0xff);
  57.         ISP_DATA  = ch;
  58.         ISP_TRIG  = 0x46;
  59.         ISP_TRIG  = 0xB9;
  60.         _nop_();
  61.         ISP_Disable();
  62. }


  63. /*********************************************************/
  64. // 擦除單片機(jī)內(nèi)部EEPROM的一個(gè)扇區(qū)
  65. // 寫8個(gè)扇區(qū)中隨便一個(gè)的地址,便擦除該扇區(qū),寫入前要先擦除
  66. /*********************************************************/
  67. void Sector_Erase(unsigned int add)          
  68. {
  69.         ISP_CONTR = 0x83;
  70.         ISP_CMD   = 0x03;
  71.         ISP_ADDRH = (unsigned char)(add>>8);
  72.         ISP_ADDRL = (unsigned char)(add&0xff);
  73.         ISP_TRIG  = 0x46;
  74.         ISP_TRIG  = 0xB9;
  75.         _nop_();
  76.         ISP_Disable();
  77. }



  78. /*********************************************************/
  79. // 毫秒級(jí)的延時(shí)函數(shù),time是要延時(shí)的毫秒數(shù)
  80. /*********************************************************/
  81. void DelayMs(uint time)
  82. {
  83.         uint i,j;
  84.         for(i=0;i<time;i++)
  85.                 for(j=0;j<112;j++);
  86. }


  87. /*********************************************************/
  88. // 1602液晶寫命令函數(shù),cmd就是要寫入的命令
  89. /*********************************************************/
  90. void LcdWriteCmd(uchar cmd)
  91. {
  92.         LcdRs_P = 0;
  93.         LcdRw_P = 0;
  94.         LcdEn_P = 0;
  95.         P0=cmd;
  96.         DelayMs(2);
  97.         LcdEn_P = 1;   
  98.         DelayMs(2);
  99.         LcdEn_P = 0;       
  100. }


  101. /*********************************************************/
  102. // 1602液晶寫數(shù)據(jù)函數(shù),dat就是要寫入的數(shù)據(jù)
  103. /*********************************************************/
  104. void LcdWriteData(uchar dat)
  105. {
  106.         LcdRs_P = 1;
  107.         LcdRw_P = 0;
  108.         LcdEn_P = 0;
  109.         P0=dat;
  110.         DelayMs(2);
  111.         LcdEn_P = 1;   
  112.         DelayMs(2);
  113.         LcdEn_P = 0;
  114. }


  115. /*********************************************************/
  116. // 液晶光標(biāo)定位函數(shù)
  117. /*********************************************************/
  118. void LcdGotoXY(uchar line,uchar column)
  119. {
  120.         // 第一行
  121.         if(line==0)        
  122.                 LcdWriteCmd(0x80+column);
  123.         // 第二行
  124.         if(line==1)        
  125.                 LcdWriteCmd(0x80+0x40+column);
  126. }



  127. /*********************************************************/
  128. // 液晶輸出字符串函數(shù)
  129. /*********************************************************/
  130. void LcdPrintStr(uchar *str)
  131. {
  132.         while(*str!='\0')
  133.                         LcdWriteData(*str++);
  134. }


  135. /*********************************************************/
  136. // 液晶輸出數(shù)字
  137. /*********************************************************/
  138. void LcdPrintNum(uint num)
  139. {
  140.         LcdWriteData(num/100+0x30);                                // 百位
  141.         LcdWriteData(num%100/10+0x30);                // 十位
  142.         LcdWriteData(num%10+0x30);                                // 個(gè)位
  143. }


  144. /*********************************************************/
  145. // 1602液晶功能初始化
  146. /*********************************************************/
  147. void LcdInit()
  148. {
  149.         LcdWriteCmd(0x38);        // 16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)口
  150.         LcdWriteCmd(0x0C);        // 開(kāi)顯示,不顯示光標(biāo)
  151.         LcdWriteCmd(0x06);        // 地址加1,當(dāng)寫入數(shù)據(jù)后光標(biāo)右移
  152.         LcdWriteCmd(0x01);        // 清屏
  153. }



  154. /*********************************************************/
  155. // 1602液晶顯示內(nèi)容初始化
  156. /*********************************************************/
  157. void LcdShowInit()
  158. {
  159.         LcdGotoXY(0,0);                                                                    // 定位到第0行第0列
  160.         LcdPrintStr("D:    cm jianghe");        // 第0行顯示"D:         "
  161. }


  162. /*********************************************************/
  163. // 計(jì)算傳感器1測(cè)量到的距離
  164. /*********************************************************/

  165. uint GetDistance1(void)
  166. {
  167.         uint ss;                                        // 用于記錄測(cè)得的距離

  168.         TH0=0;
  169.         TL0=0;

  170.         Trig1_P=1;                                // 給超聲波模塊1一個(gè)開(kāi)始脈沖
  171.         DelayMs(1);
  172.         Trig1_P=0;

  173.         while(!Echo1_P);        // 等待超聲波模塊1的返回脈沖
  174.         TR0=1;                                                // 啟動(dòng)定時(shí)器,開(kāi)始計(jì)時(shí)
  175.         while(Echo1_P);                // 等待超聲波模塊1的返回脈沖結(jié)束
  176.         TR0=0;                                                // 停止定時(shí)器,停止計(jì)時(shí)

  177.         ss=((TH0*256+TL0)*0.034)/2;                // 距離cm=(時(shí)間us * 速度cm/us)/2
  178.         return ss;
  179. }

  180. /*********************************************************/
  181. // 按鍵掃描
  182. /*********************************************************/
  183. void KeyScanf()
  184. {
  185.         if(KeySet_P==0)                                        // 判斷是否有按鍵按下
  186.         {
  187.                 LcdGotoXY(0,0);                                                                    // 光標(biāo)定位
  188.                 LcdPrintStr(" Alarm Set 1037 ");        // 第0行顯示“   Alarm Set    ”
  189.                 LcdGotoXY(1,0);                                                                                // 光標(biāo)定位
  190.                 LcdPrintStr(" alarm =     cm ");        // 第1行顯示“  alarm=   cm   ”
  191.                 LcdGotoXY(1,9);                                                                                // 光標(biāo)定位
  192.                 LcdPrintNum(gAlarm);                                                        // 顯示當(dāng)前的報(bào)警值

  193.                 DelayMs(10);                                                                                        // 消除按鍵按下的抖動(dòng)
  194.                 while(!KeySet_P);                                                                        // 等待按鍵釋放
  195.                 DelayMs(10);                                                                                        // 消除按鍵松開(kāi)的抖動(dòng)               

  196.                 while(1)
  197.                 {               
  198.                         /* 報(bào)警值減的處理 */
  199.                         if(KeyDown_P==0)                                       
  200.                         {
  201.                                 if(gAlarm>2)                                                // 報(bào)警值大于2才能減1
  202.                                         gAlarm--;                                                        // 報(bào)警值減1
  203.                                 LcdGotoXY(1,9);                                        // 光標(biāo)定位
  204.                                 LcdPrintNum(gAlarm);                // 刷新修改后的報(bào)警值
  205.                                 DelayMs(300);                                                // 延時(shí)
  206.                         }

  207.                         /* 報(bào)警值加的處理 */
  208.                         if(KeyUp_P==0)                                       
  209.                         {
  210.                                 if(gAlarm<400)                                        // 報(bào)警值小于400才能加1
  211.                                         gAlarm++;                                                        // 報(bào)警值加1
  212.                                 LcdGotoXY(1,9);                                        // 光標(biāo)定位
  213.                                 LcdPrintNum(gAlarm);                // 刷新修改后的報(bào)警值
  214.                                 DelayMs(300);                                                // 延時(shí)
  215.                         }
  216.                        
  217.                         /* 退出報(bào)警值設(shè)置 */
  218.                         if(KeySet_P==0)                                       
  219.                         {
  220.                                 break;                                                                        // 退出while循環(huán)
  221.                         }       
  222.                 }
  223.                
  224.                 LcdShowInit();                                                        // 液晶恢復(fù)測(cè)量到測(cè)量界面
  225.                 DelayMs(10);                                                          // 消除按鍵按下的抖動(dòng)
  226.                 while(!KeySet_P);                                                // 等待按鍵釋放
  227.                 DelayMs(10);                                                          // 消除按鍵松開(kāi)的抖動(dòng)               

  228.                 Sector_Erase(0x2000);                                // 保存報(bào)警距離
  229.                 EEPROM_Write(0x2000,gAlarm/100);
  230.                 EEPROM_Write(0x2001,gAlarm%100);               
  231.         }       
  232. }


  233. /*********************************************************/
  234. // 傳感器1報(bào)警判斷
  235. /*********************************************************/
  236. void AlarmJudge1(uint ss)
  237. {
  238.        
  239.         if(ss<gAlarm)                // LED燈判斷
  240.         {
  241.                 Led1_P=0;
  242.                 Buzzer_P=1;
  243.                 DelayMs(100);
  244.                 Buzzer_P=0;
  245.                 //DelayMs(100);
  246.         }
  247.         else
  248.         {
  249.                 Led1_P=1;
  250.                 Buzzer_P=0;
  251.         }


  252. }

  253. /*********************************************************/
  254. // 報(bào)警值初始化
  255. /*********************************************************/
  256. void AlarmInit()
  257. {
  258.         gAlarm=EEPROM_Read(0x2000)*100+EEPROM_Read(0x2001);                // 從EEPROM讀取報(bào)警值

  259.         if((gAlarm==0)||(gAlarm>400))                        // 如果讀取到的報(bào)警值異常(等于0或大于400則認(rèn)為異常)
  260.         {
  261.                 gAlarm=15;                                                                                        // 重新賦值報(bào)警值為15
  262.         }
  263. }


  264. /*********************************************************/
  265. // 主函數(shù)
  266. /*********************************************************/
  267. void main()
  268. {
  269.         uchar i;                                                                        // 循環(huán)變量
  270.         uint dist;                                                                // 保存測(cè)量結(jié)果

  271.         LcdInit();                                                                // 液晶功能初始化
  272.         LcdShowInit();                                                // 液晶顯示內(nèi)容初始化
  273.         AlarmInit();                                                        // 報(bào)警值初始化
  274.        
  275.         TMOD = 0x01;                                                        // 選擇定時(shí)器0,并且確定是工作方式1(為了超聲波模塊測(cè)量距離計(jì)時(shí)用的)

  276.         Trig1_P=0;                                                                // 初始化觸發(fā)引腳為低電平

  277.         while(1)
  278.         {
  279.                 /*傳感器1*/
  280.                 dist=GetDistance1();                // 讀取超聲波模塊1測(cè)量到的距離
  281.                 LcdGotoXY(0,3);                            // 光標(biāo)定位
  282.                 LcdPrintNum(dist);                        // 顯示傳感器1測(cè)量到的距離
  283.                 AlarmJudge1(dist);                        // 判斷傳感器1的測(cè)量距離是否需要報(bào)警
  284.                
  285.                 /*延時(shí)并掃描按鍵*/
  286.                 for(i=0;i<15;i++)
  287.                 {
  288.                         KeyScanf();
  289.                         DelayMs(10);
  290.                 }

  291.                
  292.         }
  293. }
復(fù)制代碼

仿真代碼資料51hei附件下載:
倒車?yán)走_(dá)系統(tǒng)設(shè)計(jì).zip (593.56 KB, 下載次數(shù): 74)


評(píng)分

參與人數(shù) 1黑幣 +30 收起 理由
admin + 30 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:1102734 發(fā)表于 2024-12-17 20:54 | 只看該作者
能不能做個(gè)前進(jìn)的障礙預(yù)警并帶有根據(jù)風(fēng)險(xiǎn)做出相應(yīng)減速保證車輛安全的功能
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表