找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 3623|回復(fù): 3
收起左側(cè)

51單片機(jī)三路超聲波避障與仿真(proteus8.6)源碼

[復(fù)制鏈接]
ID:728133 發(fā)表于 2020-4-13 13:12 | 顯示全部樓層 |閱讀模式
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.png 51hei.png

單片機(jī)源程序如下:
  1. //==============================================================================================================
  2. //程序標(biāo)題:基于51單片機(jī)的三路超聲波小車避障程序================================================================
  3. //定稿日期:-------                        ====================================================================================
  4. //作    者:-------                        ====================================================================================
  5. //更新日期:2020.3.8  23:51====================================================================================
  6. //最后撰寫人:張 虎                        ==========================================================================================
  7. //功    能:三方向避障      ====================================================================================

  8. #include<reg51.h>               //頭文件(定義了一些特殊的寄存器)
  9. #include<intrins.h>      
  10. #include<stdio.h>      
  11. //==========3個(gè)超聲波模塊定義================================
  12. sbit Trig_left    = P1^0;        //左邊超聲波模塊端口定義
  13. sbit Echo_left    = P1^1;        
  14. sbit Trig_mid     = P1^2;        //中間超聲波模塊端口定義
  15. sbit Echo_mid     = P1^3;
  16. sbit Trig_right   = P1^4;        //右邊超聲波模塊端口定義
  17. sbit Echo_right   = P1^5;
  18. //=========1個(gè)298模塊2路電機(jī)控制端設(shè)置=============================
  19. sbit N1  = P2^0;              //L298N模塊控制馬達(dá),通過N1N2和N3N4端口輸出1、0控制電機(jī)正轉(zhuǎn),反轉(zhuǎn),急停
  20. sbit N2  = P2^1;
  21. sbit N3  = P2^2;
  22. sbit N4  = P2^3;
  23. sbit EN1 = P2^4;             //L298N模塊使能端(利用PWM計(jì)數(shù)控制使能端可實(shí)現(xiàn)電機(jī)轉(zhuǎn)速控制,在本程序中沒有體現(xiàn))
  24. sbit EN2 = P2^5;                         //
  25. //============定義全局變量=======================================
  26. unsigned int  time=0;                  //定義time為十進(jìn)制無負(fù)號整型變量(0-65535),用于讀取距離

  27. unsigned long S_left=0;       //左邊障礙距離
  28. unsigned long S_mid=0;        //中間障礙距離
  29. unsigned long S_right=0;      //右邊障礙距離
  30. //==============================================================================================
  31. void delayms(unsigned int ms)  //延時(shí)子函數(shù)
  32. {
  33.         unsigned char i;
  34.         while(ms--)
  35.         {
  36.                 for(i=0;i<113;i++);
  37.         }
  38. }
  39. void delay_15us(void)   //15us精準(zhǔn)延時(shí),誤差 0us,用于啟動(dòng)超聲波模塊
  40. {
  41.     unsigned char a;
  42.     for(a=6;a>0;a--);
  43. }
  44. //=========轉(zhuǎn)向函數(shù)=============================================================================
  45. void turn_down()                         //向前
  46. {
  47. N1=1;
  48. N2=0;
  49. N3=1;
  50. N4=0;
  51. delayms(500);
  52. }
  53. void turn_back()                         //向后
  54. {
  55. N1=0;
  56. N2=1;
  57. N3=0;
  58. N4=1;
  59. delayms(500);
  60. }
  61. void turn_left()                         //向左
  62. {
  63. N1=0;
  64. N2=1;
  65. N3=1;
  66. N4=0;
  67. delayms(500);
  68. }

  69. void turn_right()                         //向右
  70. {
  71. N1=1;
  72. N2=0;
  73. N3=0;
  74. N4=1;
  75. delayms(500);
  76. }
  77. //==========啟動(dòng)超聲波模塊完成測距并讀取數(shù)值(cm)===================================================================
  78. void measure_left(void)                 //左模塊
  79. {
  80. EA=0;                                                 //關(guān)閉總中斷
  81.         Trig_left=1;                         //啟動(dòng)一次模塊,信號時(shí)間應(yīng)大于10us
  82.         delay_15us();
  83.         Trig_left=0;
  84.                               
  85.         TH1=0;                   //定時(shí)器1高8位寄存器清零
  86.     TL1=0;                   //定時(shí)器1低8位寄存器清零
  87.     TF1=0;                   //定時(shí)器1溢出位清零
  88.         while(Echo_left==0);         //當(dāng)echo為零時(shí)等待變?yōu)楦唠娖?等待波發(fā)出(Echo_lift為模塊發(fā)送超聲波到接受的時(shí)間標(biāo)志,硬件自行設(shè)置,單片機(jī)檢測即可)

  89. TR1=1;                      //波發(fā)出后立即啟動(dòng)定時(shí)器1,讓TH1,TL1寄存器數(shù)值每1us增加1。
  90. EA=1;                                     //總中斷允許,開啟計(jì)數(shù)      
  91.     while(Echo_left);        // 等待反波Echo初始狀態(tài)為0,模塊聲波發(fā)送后(聲波離開發(fā)射器),硬件將其置位,當(dāng)檢測到有聲波返回時(shí)(聲波由障礙物反射回到模塊,接收器已經(jīng)接受到聲波信號)硬件將其復(fù)位。Echo置位的時(shí)間的一半即超聲波從模塊發(fā)到障礙物止的時(shí)間S=Vt,將此時(shí)間乘以340m/s即可得到障礙物距離。
  92.         time=TH1*256+TL1;                  //取值讀取測距數(shù)值到time 將16進(jìn)制數(shù)轉(zhuǎn)化為十進(jìn)制
  93. TH1=0;                                             //清零
  94. TL1=0;
  95. TR1=0;                      //關(guān)閉定時(shí)器1
  96.         S_left=(time*17)/1000;    //轉(zhuǎn)換,定時(shí)器每1us增加1,將數(shù)值取值到time中,若初始值為0也就是從定時(shí)器開到定時(shí)器關(guān)一共經(jīng)過了time個(gè)us,微秒除1000是毫秒再除以1000是秒再乘以聲速340m/s,理論上也就是:S=Vt=【(((time÷2)÷1000 000)×340)×100】厘米,即:[(time*170)÷10000]算出來是CM(厘米)                        
  97.         delayms(5);                                 //延時(shí)
  98. }
  99. //========右邊距離測量(同左邊一樣)============================================================================================
  100. void measure_right(void)                 //左模塊
  101. {
  102. EA=0;
  103.         Trig_right=1;                           //啟動(dòng)一次模塊,信號時(shí)間應(yīng)大于10us
  104.         delay_15us();
  105.         Trig_right=0;                       
  106.         TH1=0;                   //定時(shí)器1清零
  107. TL1=0;                   //定時(shí)器1清零
  108. TF1=0;                   //溢出位清零
  109.         while(Echo_right==0);          //當(dāng)RX為零時(shí)等待變?yōu)楦唠娖剑‥cho_lift為模塊發(fā)送超聲波到接受的時(shí)間標(biāo)志,硬件自行設(shè)置,單片機(jī)檢測即可)
  110. TR1=1;                   //啟動(dòng)定時(shí)器1
  111. EA=1;                                  //開啟計(jì)數(shù)        Echo初始狀態(tài)為0,模塊聲波發(fā)送后(聲波離開發(fā)射器),硬件將其置位,當(dāng)檢測到有聲波返回時(shí)(聲波由障礙物反射回到模塊,接收器已經(jīng)接受到聲波信號)硬件將其復(fù)位。Echo置位的時(shí)間的一半即超聲波從模塊發(fā)到障礙物止的時(shí)間S=Vt,將此時(shí)間乘以340m/s即可得到障礙物距離。
  112.         while(Echo_right);                 //當(dāng)RX為1計(jì)數(shù)并等待
  113.         time=TH1*256+TL1;                  //取值讀取測距數(shù)值 將16進(jìn)制數(shù)轉(zhuǎn)化為十進(jìn)制
  114. TH1=0;                                          //清零
  115. TL1=0;
  116. TR1=0;          //關(guān)閉定時(shí)器1
  117.         S_right=(time*17)/1000;    //轉(zhuǎn)換,定時(shí)器每1us增加1,將數(shù)值取值到time中,若初始值為0也就是從定時(shí)器開到定時(shí)器關(guān)一共經(jīng)過了time個(gè)us,微秒除1000是毫秒再除以1000是秒再乘以聲速340m/s,理論上也就是:S=Vt=【(((time÷2)÷1000 000)×340)×100】厘米,即:[(time*170)÷10000]算出來是CM(厘米)
  118.                                  
  119.         delayms(5);                                 //延時(shí)
  120. }
  121. //==============中間距離測量(同左邊,右邊一樣)============================================================================
  122. void measure_mid(void)                 //左模塊
  123. {
  124. EA=0;
  125.         Trig_mid=1;                           //啟動(dòng)一次模塊,信號時(shí)間應(yīng)大于10us
  126.         delay_15us();
  127.         Trig_mid=0;                       
  128.         TH1=0;                   //定時(shí)器1清零
  129. TL1=0;                   //定時(shí)器1清零
  130. TF1=0;                   //溢出位清零

  131.         while(Echo_mid==0);          //當(dāng)RX為零時(shí)等待變?yōu)楦唠娖剑‥cho_lift為模塊發(fā)送超聲波到接受的時(shí)間標(biāo)志,硬件自行設(shè)置,單片機(jī)檢測即可)
  132. TR1=1;                   //啟動(dòng)定時(shí)器1
  133. EA=1;                                  //開啟計(jì)數(shù)        Echo初始狀態(tài)為0,模塊聲波發(fā)送后(聲波離開發(fā)射器),硬件將其置位,當(dāng)檢測到有聲波返回時(shí)(聲波由障礙物反射回到模塊,接收器已經(jīng)接受到聲波信號)硬件將其復(fù)位。Echo置位的時(shí)間的一半即超聲波從模塊發(fā)到障礙物止的時(shí)間S=Vt,將此時(shí)間乘以340m/s即可得到障礙物距離。
  134.         while(Echo_mid);                 //當(dāng)RX為1計(jì)數(shù)并等待
  135.         time=TH1*256+TL1;                  //取值讀取測距數(shù)值 將16進(jìn)制數(shù)轉(zhuǎn)化為十進(jìn)制
  136. TH1=0;                                          //清零
  137. TL1=0;
  138. TR1=0;          //關(guān)閉定時(shí)器1
  139.         S_mid=(time*17)/1000;    //轉(zhuǎn)換,定時(shí)器每1us增加1,將數(shù)值取值到time中,若初始值為0也就是從定時(shí)器開到定時(shí)器關(guān)一共經(jīng)過了time個(gè)us,微秒除1000是毫秒再除以1000是秒再乘以聲速340m/s,理論上也就是:S=Vt=【(((time÷2)÷1000 000)×340)×100】厘米,即:[(time*170)÷10000]算出來是CM(厘米)
  140.         delayms(5);                                 //延時(shí)
  141. }
  142. //=========退出死區(qū)函數(shù),===================================================================================================
  143. void move_left_or_right(void)             //設(shè)置左右轉(zhuǎn)向函數(shù)
  144. {
  145.     turn_back();                 //退出死區(qū)
  146.         N1=N2=N3=N4=1;                 //前方有障礙物,立刻"急停"然后判斷距離
  147.     delayms(100);                 //減速延遲
  148.         measure_left();      //重新檢測左前方距離
  149.         measure_right();     //重新檢測右前方距離

  150.         if(S_left>=S_right)  //左右距離不相等時(shí),通過返回?cái)?shù)據(jù)進(jìn)行避障
  151.         {
  152.                  turn_left();         //左轉(zhuǎn)
  153.                  
  154.         }
  155.         else                 //右邊距離大于左邊
  156.         {
  157.                  turn_right();         //右轉(zhuǎn)
  158.         }
  159. }
  160. //=======判斷障礙物,選擇行進(jìn)路線===================================================================================================
  161. void move(void)                           //設(shè)置前進(jìn)函數(shù)
  162. {
  163.         if(S_mid>4)                            //判斷中間障礙物的距離,單位CM(不一定準(zhǔn))
  164.                                                // 如果中間障礙物距離均大于4
  165.         {
  166.                 turn_down();                       //前進(jìn)
  167.         }
  168.         else                                                                   //判斷中間距離小于等于4,
  169.         {
  170.               N1=N2=N3=N4=1;                                   //前方有障礙物,立刻"急停"然后判斷距離
  171.                   delayms(100);                                           //減速延時(shí)
  172.                  if(S_mid<=4&&S_right>4)           //判斷右側(cè)距離是否大于4
  173.               {
  174.                           turn_right();                //右轉(zhuǎn)
  175.               }                                                                       
  176.                  else                                                           //即判斷中間及其右側(cè)距離均小于等于4
  177.                  {                                                                       
  178.                           if(S_mid<=4&&S_right<=4&&S_left>4) //判斷左側(cè)距離
  179.                                                    // 如果左側(cè)障礙物距離大于4
  180.                       {
  181.                                 turn_left();                           //左轉(zhuǎn)
  182.                       }
  183.                           else                                                   //否則 即三側(cè)均小于等于4,進(jìn)入死區(qū)模式
  184.                           {
  185.                               
  186.                             move_left_or_right();  //退出死區(qū)函數(shù)
  187.                           }
  188.                  }

  189.         }
  190. }

  191. //==========單片機(jī)定時(shí)器和計(jì)數(shù)器設(shè)置===============================================
  192. void set(void)
  193. {        delayms(10);           //上電延時(shí)
  194.         TMOD=0x10;                   //設(shè)T0為方式1,GATE=0;
  195.         TH1=0x00;                   //T1高8位重裝初值
  196.         TL1=0x00;          //T1低8位重裝初值
  197.         EA=1;                           //開啟總中斷(全局中斷)
  198.         Trig_left =0;
  199.         Trig_mid =0;
  200.         Trig_right =0;
  201.     EN1=1;                           //298模塊使能
  202.         EN2=1;
  203.         N1=N2=N3=N4=0;     //開機(jī)先制動(dòng)
  204. }
  205. //============主函數(shù)===============================================================
  206. void main(void)
  207. {
  208.         set();                                      //單片機(jī)及其298初始化
  209.         while(1)
  210.         {
  211.                 measure_left();       //檢測前方距離
  212.                 measure_mid();        //檢測前方距離
  213.                 measure_right();      //檢測前方距離
  214.                 move();               //根據(jù)檢測結(jié)果,避障前進(jìn)
  215.                 delayms(10);                  //延時(shí)
  216.         }      
  217. }
  218. //==========================================================
  219. //TH1=[(65536-設(shè)定中斷時(shí)間)/(機(jī)器運(yùn)行周期數(shù)/晶振頻率MHZ)]/256;         高8位中斷初值計(jì)算公式
  220. //TL1=[(65536-設(shè)定中斷時(shí)間)/(機(jī)器運(yùn)行周期數(shù)/晶振頻率MHZ)]%256;         低8位中斷初值計(jì)算公式
復(fù)制代碼

所有資料51hei提供下載:
三路超聲波避障(OK).7z (89.53 KB, 下載次數(shù): 73)


評分

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

查看全部評分

回復(fù)

使用道具 舉報(bào)

ID:102963 發(fā)表于 2020-4-13 22:08 | 顯示全部樓層
這狀態(tài)是怎么變換的呢?怎么一直在空擋呢?
回復(fù)

使用道具 舉報(bào)

ID:848219 發(fā)表于 2020-11-24 11:06 | 顯示全部樓層
這個(gè)怎么改變狀態(tài)
回復(fù)

使用道具 舉報(bào)

ID:725587 發(fā)表于 2020-11-24 16:54 | 顯示全部樓層
先點(diǎn)贊 再慢慢看
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

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

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

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