久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5968|回復: 4
打印 上一主題 下一主題
收起左側

單片機超聲波測距+溫度補償源程序與Proteus仿真圖

  [復制鏈接]
跳轉到指定樓層
樓主
ID:955584 發表于 2021-7-22 23:43 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
超聲波測距仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機源程序如下:
  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;            // 數據寄存器
  6. sfr ISP_ADDRH = 0xe3;            // 地址寄存器高八位
  7. sfr ISP_ADDRL = 0xe4;            // 地址寄存器低八位
  8. sfr ISP_CMD   = 0xe5;            // 命令寄存器
  9. sfr ISP_TRIG  = 0xe6;            // 命令觸發寄存器
  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 Trig_P    = P2^2;        // 超聲波模塊的Trig管腳
  15. sbit Echo_P    = P2^3;        // 超聲波模塊的Echo管腳
  16. sbit KeySet_P  = P3^2;        // “設置”按鍵的管腳
  17. sbit KeyDown_P = P3^3;        // “減”按鍵的管腳
  18. sbit KeyUp_P   = P3^4;        // “加”按鍵的管腳
  19. sbit Buzzer_P  = P2^1;        // 蜂鳴器的管腳
  20. sbit Led_P     = P2^0;        // LED報警燈的管腳
  21. sbit DQ        = P1^0;        // 溫度傳感器的引腳定義


  22. uint  gAlarm;                            // 報警距離變量
  23. float gSpeed;                            // 保存超聲波的速度值




  24. /*********************************************************/
  25. // 擦除單片機內部EEPROM的一個扇區
  26. // 寫8個扇區中隨便一個的地址,便擦除該扇區,寫入前要先擦除
  27. /*********************************************************/
  28. void Sector_Erase(unsigned int add)      
  29. {
  30.     ISP_CONTR = 0x83;
  31.     ISP_CMD   = 0x03;
  32.     ISP_ADDRH = (unsigned char)(add>>8);
  33.     ISP_ADDRL = (unsigned char)(add&0xff);
  34.     ISP_TRIG  = 0x46;
  35.     ISP_TRIG  = 0xB9;
  36.     _nop_();
  37.     ISP_Disable();
  38. }



  39. /*********************************************************/
  40. // 毫秒級的延時函數,time是要延時的毫秒數
  41. /*********************************************************/
  42. void DelayMs(uint time)
  43. {
  44.     uint i,j;
  45.     for(i=0;i<time;i++)
  46.         for(j=0;j<112;j++);
  47. }



  48. /*********************************************************/
  49. // 讀取溫度值
  50. /*********************************************************/
  51. int DS18B20_ReadTemp(void)
  52. {
  53.     uchar j;
  54.     int b,temp=0;   

  55.     DS18B20_ReSet();                            // 產生復位脈
  56.     DS18B20_WriteByte(0xcc);            // 忽略ROM指令
  57.     DS18B20_WriteByte(0x44);            // 啟動溫度轉換指令

  58.     DS18B20_ReSet();                            // 產生復位脈
  59.     DS18B20_WriteByte(0xcc);            // 忽略ROM指令
  60.     DS18B20_WriteByte(0xbe);            // 讀取溫度指令

  61.     for(j=0;j<16;j++)                            // 讀取溫度數量
  62.     {                        
  63.         DQ=0;
  64.         _nop_();
  65.         _nop_();
  66.         DQ=1;   
  67.         Delay15us();
  68.         b=DQ;
  69.         Delay15us();
  70.         Delay15us();
  71.         Delay15us();
  72.         b=b<<j;
  73.         temp=temp|b;
  74.     }
  75.    
  76.     temp=temp*0.0625*10;                    // 合成溫度值并放大10倍                    
  77.     return (temp);                                // 返回檢測到的溫度值
  78. }



  79. /*********************************************************/
  80. // 計算測到的距離
  81. /*********************************************************/
  82. uint GetDistance(void)
  83. {
  84.     uint ss;                    // 用于記錄測得的距離

  85.     TH0=0;
  86.     TL0=0;

  87.     Trig_P=1;                    // 給超聲波模塊一個開始脈沖
  88.     DelayMs(1);
  89.     Trig_P=0;

  90.     while(!Echo_P);        // 等待超聲波模塊的返回脈沖
  91.     TR0=1;                        // 啟動定時器,開始計時
  92.     while(Echo_P);        // 等待超聲波模塊的返回脈沖結束
  93.     TR0=0;                        // 停止定時器,停止計時

  94.     ss=((TH0*256+TL0)*gSpeed)/2;        // 距離cm=(時間us * 速度cm/us)/2

  95.     if(ss>999)                // 把檢測結果限制999厘米內
  96.         ss=999;
  97.    
  98.     return ss;
  99. }


  100. /*********************************************************/
  101. // 按鍵掃描
  102. /*********************************************************/
  103. void KeyScanf()
  104. {
  105.     uchar i;
  106.     uchar dat1,dat2;

  107.     if(KeySet_P==0)                                // 判斷是否有按鍵按下
  108.     {
  109.         LcdGotoXY(1,0);                            // 液晶第二行刷新顯示
  110.         LcdPrintStr("  alarm=   cm   ");
  111.         LcdGotoXY(1,8);                            // 顯示當前的報警值
  112.         LcdPrintNum(gAlarm);               
  113.         
  114.         DelayMs(10);                                // 消除按鍵按下的抖動
  115.         while(!KeySet_P);                        // 等待按鍵釋放
  116.         DelayMs(10);                                // 消除按鍵松開的抖動

  117.         i=1;

  118.         while(i)
  119.         {                              
  120.             if(KeyDown_P==0)        // 報警值減的處理
  121.             {
  122.                 if(gAlarm>2)
  123.                     gAlarm--;
  124.                 LcdGotoXY(1,8);
  125.                 LcdPrintNum(gAlarm);   
  126.                 DelayMs(300);
  127.             }

  128.             if(KeyUp_P==0)            // 報警值加的處理
  129.             {
  130.                 if(gAlarm<400)
  131.                     gAlarm++;
  132.                 LcdGotoXY(1,8);
  133.                 LcdPrintNum(gAlarm);
  134.                 DelayMs(300);
  135.             }
  136.             
  137.             if(KeySet_P==0)            // 再次按下設置鍵的判斷
  138.             {
  139.                 LcdGotoXY(1,0);                        // 液晶恢復測量時的內容顯示
  140.                 LcdPrintStr("  dist=   cm    ");
  141.                 DelayMs(10);                          // 消除按鍵按下的抖動
  142.                 while(!KeySet_P);                    // 等待按鍵釋放
  143.                 DelayMs(10);                          // 消除按鍵松開的抖動
  144.                 i=0;
  145.             }               
  146.         }
  147.         
  148.         dat1=gAlarm/100;
  149.         dat2=gAlarm%100;
  150.         Sector_Erase(0x2000);
  151.         EEPROM_Write(0x2000,dat1);
  152.         EEPROM_Write(0x2001,dat2);
  153.     }   
  154. }


  155. /*********************************************************/
  156. // 報警判斷
  157. /*********************************************************/
  158. void AlarmJudge(uint ss)
  159. {
  160.     uchar i;
  161.     float alr1,alr2,alr3,alr4;

  162.     alr1=gAlarm/4.00*1;
  163.     alr2=gAlarm/4.00*2;
  164.     alr3=gAlarm/4.00*3;
  165.     alr4=gAlarm/4.00*4;


  166.     // 報警頻率最快
  167.     if(ss<alr1)            
  168.     {
  169.         for(i=0;i<10;i++)
  170.         {
  171.             Led_P=0;
  172.             Buzzer_P=0;
  173.             DelayMs(50);
  174.             Led_P=1;
  175.             Buzzer_P=1;
  176.             DelayMs(50);
  177.             KeyScanf();
  178.         }
  179.     }
  180.     // 報警頻率第二快
  181.     else if(ss<alr2)        
  182.     {
  183.         for(i=0;i<5;i++)
  184.         {
  185.             Led_P=0;
  186.             Buzzer_P=0;
  187.             DelayMs(100);
  188.             Led_P=1;
  189.             Buzzer_P=1;
  190.             DelayMs(100);
  191.             KeyScanf();
  192.         }   
  193.     }
  194.     // 報警頻率第三快
  195.     else if(ss<alr3)     
  196.     {
  197.         for(i=0;i<2;i++)
  198.         {
  199.             Led_P=0;
  200.             Buzzer_P=0;
  201.             DelayMs(200);
  202.             Led_P=1;
  203.             Buzzer_P=1;
  204.             DelayMs(200);
  205.             KeyScanf();
  206.         }   
  207.     }
  208.     // 報警頻率最慢
  209.     else if(ss<alr4)   
  210.     {
  211.         for(i=0;i<2;i++)
  212.         {
  213.             Led_P=0;
  214.             Buzzer_P=0;
  215.             DelayMs(300);
  216.             Led_P=1;
  217.             Buzzer_P=1;
  218.             DelayMs(300);
  219.             KeyScanf();
  220.         }   
  221.     }
  222.     // 不報警
  223.     else
  224.     {
  225.         Led_P=1;
  226.         Buzzer_P=1;
  227.         for(i=0;i<100;i++)
  228.         {
  229.             KeyScanf();
  230.             DelayMs(10);
  231.         }   
  232.     }
  233. }


  234. /*********************************************************/
  235. // 主函數
  236. /*********************************************************/
  237. void main()
  238. {
  239.     uchar dat1,dat2;
  240.     uint dist;                                                // 保存超聲波模塊測量到的結果
  241.     int  temp;                                                // 保存溫度傳感器測量到的結果

  242.     Trig_P=0;
  243.    
  244.     LcdInit();                                                // 執行液晶初始化
  245.     TMOD = 0x01;                                            // 選擇定時器0,并且確定是工作方式1(為了超聲波模塊測量距離計時用的)
  246.    
  247.     LcdGotoXY(0,0);                                    // 定位到第0行第0列
  248.     LcdPrintStr("  temp=         ");    // 第0行顯示“  temp=         ”
  249.     LcdGotoXY(1,0);                                    // 定位到第1行第0列
  250.     LcdPrintStr("  dist=   cm    ");    // 第1行顯示“  dist=   cm    ”

  251.     while(DS18B20_ReadTemp()==850)        // 等待溫度傳感器初始化完成
  252.     {
  253.         DelayMs(10);
  254.     }
  255.    
  256.     dat1=EEPROM_Read(0x2000);                    // 從EEPROM讀取報警值
  257.     dat2=EEPROM_Read(0x2001);
  258.     gAlarm=dat1*100+dat2;

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

  263.     while(1)
  264.     {
  265.         temp=DS18B20_ReadTemp();                // 獲取溫度傳感器的溫度值
  266.         LcdGotoXY(0,7);                                    // 定位到第0行第7列
  267.         LcdPrintTemp(temp);                            // 顯示當前的溫度值
  268.         
  269.         gSpeed=0.607*(temp/10)+331.4;        // 根據公式 v=0.607T+331.4 計算出當前溫度值對應的超聲波速度,這時的單位是“米/秒”
  270.         gSpeed=gSpeed/10000;                        // 將超聲波的速度從單位“m/s”轉為“cm/us”,方便后面的計算
  271.         
  272.         dist=GetDistance();                            // 通過超聲波模塊獲取距離
  273.         LcdGotoXY(1,7);                                // 光標定位
  274.         LcdPrintNum(dist);                            // 將獲取到的距離在液晶上面顯示

  275.         AlarmJudge(dist);                                // 判斷一下是否需要報警,是的話則報警   
  276.     }
  277. }
  278. ……………………

  279. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

仿真代碼51hei附件下載:
超聲波測距+溫度補償 proteus仿真.zip (144.92 KB, 下載次數: 205)

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

沙發
ID:959083 發表于 2021-8-5 19:47 | 只看該作者
大佬收下我的膝蓋。
回復

使用道具 舉報

板凳
ID:792997 發表于 2021-9-27 08:36 來自手機 | 只看該作者
好牛,不愧是大佬
回復

使用道具 舉報

地板
ID:1086127 發表于 2023-6-27 18:03 | 只看該作者
你好,請問為什么打開之后有很多未定義錯誤啊
回復

使用道具 舉報

5#
ID:40039 發表于 2023-8-12 20:50 | 只看該作者
程序打不開,是我的版本太低了?
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 韩三级在线观看 | 亚洲乱码一区二区三区在线观看 | 久久久久久九九九九九九 | 日韩av在线一区二区 | 国产区第一页 | 亚洲精品成人网 | 亚洲国产高清免费 | 久久精品日产第一区二区三区 | 亚洲国产精品久久久久秋霞不卡 | 99国产精品99久久久久久 | 久久成人一区 | 日韩中文字幕在线观看 | www.黄色网 | 精品伊人久久 | 红桃视频一区二区三区免费 | 久久三区 | 久久久久久久久国产 | 国产精品91网站 | 日本三级网址 | 国产一区二区三区免费观看视频 | 亚洲啊v| 中文字幕91av | 在线āv视频 | 91视频在线观看免费 | 欧美在线一区二区三区 | 精品久久久久久亚洲综合网 | 国产jizz女人多喷水99 | 日韩在线中文字幕 | 一本一道久久a久久精品综合 | 男人的天堂久久 | 亚洲成人精品影院 | 精品av天堂毛片久久久借种 | 亚洲乱码一区二区三区在线观看 | 亚洲精品大全 | 日本免费在线看 | 自拍视频精品 | 黄色a三级 | 国产色99 | 亚洲草草视频 | 羞羞免费网站 | 日韩三片 |