找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

基于51單片機多路超聲波顯示源程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:699194 發(fā)表于 2020-4-29 00:35 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
本人測試成功,程序絕對可用的

單片機源程序如下:
  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   = P2^7;                // 1602液晶的RS管腳      
  12. sbit LcdRw_P   = P2^6;                // 1602液晶的RW管腳
  13. sbit LcdEn_P   = P2^5;                // 1602液晶的EN管腳
  14. sbit Trig1_P   = P2^3;                // 超聲波模塊1的Trig管腳
  15. sbit Echo1_P   = P2^4;                // 超聲波模塊1的Echo管腳
  16. sbit Trig2_P   = P1^5;                // 超聲波模塊2的Trig管腳
  17. sbit Echo2_P   = P1^6;                // 超聲波模塊2的Echo管腳
  18. sbit KeySet_P  = P1^0;                // 設(shè)置按鍵的管腳
  19. sbit KeyDown_P = P1^1;                // 減按鍵的管腳
  20. sbit KeyUp_P   = P1^2;                // 加按鍵的管腳
  21. sbit Buzzer_P  = P2^0;                // 蜂鳴器的管腳
  22. sbit Led1_P    = P2^2;                // 傳感器1報警燈
  23. sbit Led2_P    = P3^3;                // 傳感器2報警燈

  24. uint gAlarm;                                                        // 報警距離變量



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


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


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


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



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


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


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


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



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


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


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



  157. /*********************************************************/
  158. // 1602液晶顯示內(nèi)容初始化
  159. /*********************************************************/
  160. void LcdShowInit()
  161. {
  162.         LcdGotoXY(0,0);                                                                    // 定位到第0行第0列
  163.         LcdPrintStr("  dist1=   cm   ");        // 第0行顯示“  dist1=   cm   ”
  164.         LcdGotoXY(1,0);                                                                    // 定位到第1行第0列
  165.         LcdPrintStr("  dist2=   cm   ");        // 第1行顯示“  dist2=   cm   ”
  166. }


  167. /*********************************************************/
  168. // 計算傳感器1測量到的距離
  169. /*********************************************************/
  170. uint GetDistance1(void)
  171. {
  172.         uint ss;                                        // 用于記錄測得的距離

  173.         TH0=0;
  174.         TL0=0;

  175.         Trig1_P=1;                                // 給超聲波模塊1一個開始脈沖
  176.         DelayMs(1);
  177.         Trig1_P=0;

  178.         while(!Echo1_P);        // 等待超聲波模塊1的返回脈沖
  179.         TR0=1;                                                // 啟動定時器,開始計時
  180.         while(Echo1_P);                // 等待超聲波模塊1的返回脈沖結(jié)束
  181.         TR0=0;                                                // 停止定時器,停止計時

  182.         ss=((TH0*256+TL0)*0.034)/2;                // 距離cm=(時間us * 速度cm/us)/2
  183.         return ss;
  184. }


  185. /*********************************************************/
  186. // 計算傳感器2測量到的距離
  187. /*********************************************************/
  188. uint GetDistance2(void)
  189. {
  190.         uint ss;                                        // 用于記錄測得的距離

  191.         TH0=0;
  192.         TL0=0;

  193.         Trig2_P=1;                                // 給超聲波模塊2一個開始脈沖
  194.         DelayMs(1);
  195.         Trig2_P=0;

  196.         while(!Echo2_P);        // 等待超聲波模塊2的返回脈沖
  197.         TR0=1;                                                // 啟動定時器,開始計時
  198.         while(Echo2_P);                // 等待超聲波模塊2的返回脈沖結(jié)束
  199.         TR0=0;                                                // 停止定時器,停止計時

  200.         ss=((TH0*256+TL0)*0.034)/2;                // 距離cm=(時間us * 速度cm/us)/2
  201.         return ss;
  202. }


  203. /*********************************************************/
  204. // 按鍵掃描
  205. /*********************************************************/
  206. void KeyScanf()
  207. {
  208.         if(KeySet_P==0)                                        // 判斷是否有按鍵按下
  209.         {
  210.                 LcdGotoXY(0,0);                                                                    // 光標定位
  211.                 LcdPrintStr("   Alarm Set    ");        // 第0行顯示“   Alarm Set    ”
  212.                 LcdGotoXY(1,0);                                                                                // 光標定位
  213.                 LcdPrintStr("  alarm=   cm   ");        // 第1行顯示“  alarm=   cm   ”
  214.                 LcdGotoXY(1,8);                                                                                // 光標定位
  215.                 LcdPrintNum(gAlarm);                                                        // 顯示當(dāng)前的報警值

  216.                 DelayMs(10);                                                                                        // 消除按鍵按下的抖動
  217.                 while(!KeySet_P);                                                                        // 等待按鍵釋放
  218.                 DelayMs(10);                                                                                        // 消除按鍵松開的抖動               

  219.                 while(1)
  220.                 {               
  221.                         /* 報警值減的處理 */
  222.                         if(KeyDown_P==0)                                       
  223.                         {
  224.                                 if(gAlarm>2)                                                // 報警值大于2才能減1
  225.                                         gAlarm--;                                                        // 報警值減1
  226.                                 LcdGotoXY(1,8);                                        // 光標定位
  227.                                 LcdPrintNum(gAlarm);                // 刷新修改后的報警值
  228.                                 DelayMs(300);                                                // 延時
  229.                         }

  230.                         /* 報警值加的處理 */
  231.                         if(KeyUp_P==0)                                       
  232.                         {
  233.                                 if(gAlarm<400)                                        // 報警值小于400才能加1
  234.                                         gAlarm++;                                                        // 報警值加1
  235.                                 LcdGotoXY(1,8);                                        // 光標定位
  236.                                 LcdPrintNum(gAlarm);                // 刷新修改后的報警值
  237.                                 DelayMs(300);                                                // 延時
  238.                         }
  239.                        
  240.                         /* 退出報警值設(shè)置 */
  241.                         if(KeySet_P==0)                                       
  242.                         {
  243.                                 break;                                                                        // 退出while循環(huán)
  244.                         }       
  245.                 }
  246.                
  247.                 LcdShowInit();                                                        // 液晶恢復(fù)測量到測量界面
  248.                 DelayMs(10);                                                          // 消除按鍵按下的抖動
  249.                 while(!KeySet_P);                                                // 等待按鍵釋放
  250.                 DelayMs(10);                                                          // 消除按鍵松開的抖動               

  251.                 Sector_Erase(0x2000);                                // 保存報警距離
  252.                 EEPROM_Write(0x2000,gAlarm/100);
  253.                 EEPROM_Write(0x2001,gAlarm%100);               
  254.         }       
  255. }


  256. /*********************************************************/
  257. // 傳感器1報警判斷
  258. /*********************************************************/
  259. void AlarmJudge1(uint ss)
  260. {
  261.         if(ss<gAlarm)                // LED燈判斷
  262.         {
  263.                 Led1_P=0;
  264.         }
  265.         else
  266.         {
  267.                 Led1_P=1;
  268.         }
  269.        
  270.         if((Led1_P==0)||(Led2_P==0))        // 蜂鳴器判斷
  271.         {
  272.                 Buzzer_P=0;
  273.         }
  274.         else
  275.         {
  276.                 Buzzer_P=1;
  277.         }
  278. }


  279. /*********************************************************/
  280. // 傳感器2報警判斷
  281. /*********************************************************/
  282. void AlarmJudge2(uint ss)
  283. {
  284.         if(ss<gAlarm)                // LED燈判斷
  285.         {
  286.                 Led2_P=0;
  287.         }
  288.         else
  289.         {
  290.                 Led2_P=1;
  291.         }
  292.        
  293.         if((Led1_P==0)||(Led2_P==0))        // 蜂鳴器判斷
  294.         {
  295.                 Buzzer_P=0;
  296.         }
  297.         else
  298.         {
  299.                 Buzzer_P=1;
  300.         }
  301. }


  302. /*********************************************************/
  303. // 報警值初始化
  304. /*********************************************************/
  305. void AlarmInit()
  306. {
  307.         gAlarm=EEPROM_Read(0x2000)*100+EEPROM_Read(0x2001);                // 從EEPROM讀取報警值

  308.         if((gAlarm==0)||(gAlarm>400))                        // 如果讀取到的報警值異常(等于0或大于400則認為異常)
  309.         {
  310.                 gAlarm=25;                                                                                        // 重新賦值報警值為25
  311.         }
  312. }



  313. /*********************************************************/
  314. // 主函數(shù)
  315. /*********************************************************/
  316. void main()
  317. {
  318.         uchar i;                                                                        // 循環(huán)變量
  319.         uint dist;                                                                // 保存測量結(jié)果

  320.         LcdInit();                                                                // 液晶功能初始化
  321.         LcdShowInit();                                                // 液晶顯示內(nèi)容初始化
  322.         AlarmInit();                                                        // 報警值初始化
  323.        
  324.         TMOD = 0x01;                                                        // 選擇定時器0,并且確定是工作方式1(為了超聲波模塊測量距離計時用的)

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

  327.         while(1)
  328.         {
  329.                 /*傳感器1*/
  330.                 dist=GetDistance1();                // 讀取超聲波模塊1測量到的距離
  331.                 LcdGotoXY(0,8);                            // 光標定位
  332.                 LcdPrintNum(dist);                        // 顯示傳感器1測量到的距離
  333.                 AlarmJudge1(dist);                        // 判斷傳感器1的測量距離是否需要報警
  334.                
  335.                 /*延時并掃描按鍵*/
  336.                 for(i=0;i<20;i++)
  337.                 {
  338.                         KeyScanf();
  339.                         DelayMs(10);
  340.                 }
  341.                
  342.                 /*傳感器2*/
  343.                 dist=GetDistance2();                // 讀取超聲波模塊2測量到的距離
  344.                 LcdGotoXY(1,8);                            // 光標定位
  345.                 LcdPrintNum(dist);                        // 顯示傳感器2測量到的距離
  346.                 AlarmJudge2(dist);                        // 判斷傳感器2的測量距離是否需要報警
  347.                
  348.                 /*延時并掃描按鍵*/
  349.                 for(i=0;i<20;i++)
  350.                 {
  351.                         KeyScanf();
  352.                         DelayMs(10);
  353.                 }
  354.         }
  355. }
復(fù)制代碼

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

使用道具 舉報

沙發(fā)
ID:632112 發(fā)表于 2020-5-20 09:33 | 只看該作者
正在找呢,謝謝樓主
回復(fù)

使用道具 舉報

板凳
ID:761098 發(fā)表于 2020-5-28 09:18 | 只看該作者
樓主 有沒有測量的數(shù)據(jù)?
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

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