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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

基于51單片機的超聲波測距設計(帶溫度補償)

  [復制鏈接]
跳轉到指定樓層
樓主
ID:189697 發表于 2017-7-6 09:41 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
利用STC89C52單片機、超聲波模塊(HC-RS04)、DS18B20數字溫度傳感器和LCD1602液晶顯示模塊制作一個超聲波測距儀,液晶屏第一行顯示溫度和超聲波速度“T:30°C  V:349m/s”,第二行顯示測量距離“S=X.XXXm”。
所設計的測距儀測量單位為米,精確到小數點后面3位(毫米),測量范圍:0.05m~5m。
(一)基本部分
1、液晶顯示功能
(1)開機時,液晶屏第一行顯示溫度和超聲波速度,例如“T:30°C  V:349m/s”,第二行顯示測量距離“S=0.000m”
(2)操作對應的功能按鍵時,液晶屏第一行顯示溫度和超聲波速度,例如“T:30°C  V:349m/s”,第二行顯示測量距離“S=X.XXXm”。
(3)本超聲波測距儀使用4個獨立按鍵。第1個按鍵為復位清零功能;第2個按鍵為單次測量功能;第3個按鍵為瞬時連續測量功能;第4個按鍵為平均連續測量功能。
(4)第1個按鍵為復位清零功能。無論什么時候按下該鍵,液晶屏第二行均顯示測量距離“S=0.000m”
(5)第2個按鍵為單次測量功能。每按一次該鍵,就發射一次超聲波,液晶屏第二行對應顯示一次測量距離“S=X.XXXm”
(6)第3個按鍵為瞬時連續測量功能。按下該鍵,連續發射超聲波,液晶屏第二行對應顯示瞬時測量距離“S=X.XXXm”,再按一次該鍵,數字保持,以便讀數
(7)第4個按鍵為平均連續測量功能。按下該鍵,連續發射超聲波,液晶屏第二行對應顯示平均測量距離“S=X.XXXm”,再按一次該鍵,數字保持,以便讀數

(8)第5個按鍵為自動/手動溫度設置按鍵,轉換到手動設置溫度值,這時可以利用加鍵和減鍵使溫度在0度至50度范圍內調節,再按一次該鍵,重新回到自動溫控狀態,如此循環。
(9)第6個按鍵為溫度加按鍵,當處于手動溫度控制狀態時,按下本按鍵可以加溫度,最高可以加到50攝氏度。
(10)第7個按鍵為溫度減按鍵,當處于手動溫度控制狀態時,按下本按鍵可以減溫度,最低可以減0攝氏度。

程序代碼如下:
  1. /**************************************/
  2. /*   超聲波測距(自動/手動溫度校正)  */
  3. /*   (超聲波模塊+18B20+1602液晶)    */
  4. /**************************************/
  5. #include <reg52.h>
  6. #include <intrins.h>
  7. #define uchar unsigned char
  8. #define uint unsigned int
  9. #define LcdData P0                   //1602數據端口

  10. sbit LCD_RS=P2^6;      //1602 RS端口
  11. sbit LCD_RW=P2^5;      //1602 RW端口
  12. sbit LCD_EN=P2^7;      //1602 EN端口
  13. sbit Echo=P2^4;        //HC-SR04 接收端口
  14. sbit Trig=P2^3;        //HC-SR04 發射端口
  15. sbit Resets_Key=P1^0;  //復位清零按鍵
  16. sbit Single_Key=P1^1;  //單次測量按鍵    誤差較大
  17. sbit Contin_Key=P1^2;  //連續測量按鍵    誤差小
  18. sbit Averag_Key=P1^3;  //連續(平均測量)按鍵   誤差較小
  19. sbit Setting_Key=P1^4; //溫度修正按鍵
  20. sbit Add_Key=P1^5;     //溫度加1按鍵
  21. sbit Sub_Key=P1^6;     //溫度減1按鍵
  22. sbit DQ=P3^7;          //DS18B20單總線接口

  23. bit Temp_Flag;         //正負溫度標志:溫度為正Temp_Flag=0,否則為1
  24. uint temp=25;          //溫度值
  25. bit flag_flow=0,flag_one=0,flag_clear=0,flag_con1=0,flag_con2=0,flag_temp=0;
  26. uchar i=0,m,j,k;
  27. uint time=0,S=0,S1=0,totle=0;
  28. float V=346.0;
  29. uint Sav[11];                                                          //連續測量時10次平均值數組
  30. uchar Line1[16]={"T:   C  V:346m/s"};          //1602第一行初始字符顯示數組
  31. uchar Line2[16]={"S=     m        "};          //1602第二行初始字符顯示數組

  32. void Delayms(uchar xms);                        //延時xms函數
  33. void WriteLcd(uchar Dat,bit x);        //1602寫函數
  34. void InitLcd(void);                                //1602初始化函數
  35. void DisplayLcd();                                //1602顯示函數
  36. void init();                                        //初始化函數
  37. void keyscan();                                        //鍵掃描函數
  38. void StartModule();                            //啟動模塊函數
  39. void Conut(void);                                 //測量計算函數
  40. void Delayus(uchar xus);        //us級延時函數
  41. bit Init_DS18B20(void);         //初始化DS18B20函數
  42. uchar Read_DS18B20(void);       //讀DS18B20函數
  43. void Write_DS18B20(uchar Dat);  //寫DS18B20函數
  44. void GetTemp();                 //取溫度函數
  45. void CalcTestTemp();            //溫度處理函數

  46. void main(void)    //主函數
  47. {
  48.         init();
  49.         InitLcd();
  50.         while(1)
  51.         {
  52.                 keyscan();                         //鍵掃描函數
  53.             DisplayLcd();
  54.             if(flag_temp==0)
  55.             {
  56.                     GetTemp();
  57.                     CalcTestTemp();
  58.             }
  59.             if(flag_one==1||flag_con1==1||flag_con2==1)
  60.             {
  61.                     StartModule();         //開始發射超聲波
  62.                 while(!Echo);                 //當RX為零時等待
  63.             TR0=1;                         //開啟計數
  64.             while(Echo);             //當RX為1計數并等待
  65.                 TR0=0;                         //關閉計數
  66.             Conut();                 //計算
  67.             Delayus(200);
  68.                 flag_one=0;
  69.             }
  70.         }
  71. }

  72. void Delayms(uchar xms)   //延時ms函數
  73. {
  74.     uchar i,j;
  75.     for(i=xms;i>0;i--)
  76.             for(j=110;j>0;j--);
  77. }

  78. void WriteLcd(uchar Dat,bit x)  //1602寫函數(寫指令時x=0,寫數據時x=1)
  79. {
  80.         LCD_EN=0;
  81.         LcdData=Dat;
  82.         LCD_RS=x;
  83.         LCD_RW=0;
  84.         LCD_EN=1;
  85.         Delayms(1);
  86.         LCD_EN=0;
  87. }

  88. void InitLcd(void)           //1602初始化函數
  89. {
  90.         WriteLcd(0x38,0);  //功能設定(38H),8位數據,2行顯示,5*7點陣
  91.         WriteLcd(0x0C,0);  //顯示開、關設定(0CH),開顯示,不顯示光標,光標不閃爍
  92.         WriteLcd(0x06,0);  //輸入模式設定(06H),讀寫一個字符后,地址指針加1,且光標加1
  93.         WriteLcd(0x01,0);  //清除顯示(01H),清除數據RAM中的數據
  94. }

  95. void DisplayLcd()                                  //液晶屏顯示函數
  96. {
  97.     uchar y;
  98.     V=(331.4+temp*0.607);
  99.     Line1[2]=temp/10+0x30;
  100.     Line1[3]=temp%10+0x30;
  101.     Line1[4]=0xDF;                  //顯示℃中C前面的小圓
  102.     Line1[10]=(uint)V/100+0x30;
  103.     Line1[11]=(uint)V%100/10+0x30;
  104.     Line1[12]=(uint)V%10+0x30;
  105.     if(flag_clear==1)
  106.     S1=0;
  107.     if((S1>=7000)||flag_flow==1)    //超出測量范圍顯示“-”
  108.         {         
  109.             flag_flow=0;
  110.             Line2[2]='-';
  111.             Line2[3]='.';
  112.             Line2[4]='-';
  113.             Line2[5]='-';
  114.             Line2[6]='-';
  115.         }
  116.     else
  117.         {
  118.             Line2[2]=S1/1000+0x30;
  119.             Line2[3]='.';
  120.             Line2[4]=S1%1000/100+0x30;
  121.             Line2[5]=S1%100/10+0x30;
  122.             Line2[6]=S1%10+0x30;
  123.         }
  124.     WriteLcd(0x80,0);               //設定第一行地址
  125.     for(y=0; y<16; y++)
  126.         WriteLcd(Line1[y],1);
  127.     WriteLcd(0xc0,0);               //設定第二行地址
  128.     for(y=0; y<16; y++)
  129.         WriteLcd(Line2[y],1);
  130. }

  131. void init()        //初始化函數
  132. {
  133.     TMOD=0x01;        //設T0為方式1,GATE=1;
  134.     TH0=0;
  135.     TL0=0;         
  136.     ET0=1; //允許T0中斷
  137.     EA=1;  //開啟總中斷
  138. }

  139. void keyscan()                         //鍵掃描函數
  140. {
  141.     if(Resets_Key==0)                         //復位清零鍵
  142.     {
  143.         Delayms(5);
  144.         if(Resets_Key==0)
  145.         {
  146.                 while(Resets_Key==0);
  147.             flag_clear=1;
  148.             }
  149.     }
  150.     if(Single_Key==0)                         //單次測量鍵
  151.     {
  152.         Delayms(5);
  153.         if(Single_Key==0)
  154.         {
  155.                 while(Single_Key==0);
  156.                 flag_one=1;
  157.             flag_con1=0;
  158.                 flag_con2=0;
  159.                 flag_clear=0;
  160.             }
  161.     }
  162.     if(Contin_Key==0)                         //連續瞬時測量鍵
  163.     {
  164.         Delayms(5);
  165.         if(Contin_Key==0)
  166.         {
  167.                 while(Contin_Key==0);
  168.                 flag_con1=~flag_con1;
  169.                 if(flag_con1==1)
  170.                 {
  171.                     flag_one=0;
  172.                     flag_con2=0;
  173.                     flag_clear=0;
  174.                 }
  175.             }
  176.     }
  177.     if(Averag_Key==0)                        //連續平均測量鍵
  178.     {
  179.         Delayms(5);
  180.         if(Averag_Key==0)
  181.         {
  182.                 while(Averag_Key==0);
  183.                 flag_con2=~flag_con2;
  184.                 if(flag_con2==1)
  185.                 {
  186.                     flag_one=0;
  187.                     flag_con1=0;
  188.                     flag_clear=0;
  189.                 }
  190.             }
  191.     }
  192.     if(Setting_Key==0)                   //自動和手動轉換鍵
  193.     {
  194.         Delayms(5);
  195.         if(Setting_Key==0)
  196.         {
  197.                  while(Setting_Key==0);
  198.                  flag_temp=~flag_temp;
  199.             }
  200.     }
  201.     if(Add_Key==0)                   //溫度減鍵
  202.     {
  203.         Delayms(5);
  204.         if(Add_Key==0)
  205.         {
  206.                 while(Add_Key==0);
  207.                 if(flag_temp==1)
  208.                 {
  209.                 temp++;
  210.                     if(temp>=50)
  211.                     temp=50;
  212.                 }
  213.             }
  214.     }
  215.     if(Sub_Key==0)                   //溫度加鍵
  216.     {
  217.         Delayms(5);
  218.         if(Sub_Key==0)
  219.         {
  220.                 while(Sub_Key==0);
  221.                 if(flag_temp==1)
  222.                 {
  223.                     if(temp>0)
  224.                 temp--;
  225.                     if(temp<=0)
  226.                     temp=0;
  227.                 }
  228.             }
  229.     }
  230. }

  231. void StartModule()                        //啟動模塊函數(觸發一次,提供大于10us的高電平)
  232. {
  233.     Trig=1;                                       //啟動一次模塊
  234.     Delayus(15);                                    //延時2i+5=35us
  235.     Trig=0;
  236. }

  237. void Conut(void)                           //測量計算函數
  238. {
  239.     time=TH0*256+TL0;
  240.     TH0=0;
  241.     TL0=0;
  242.     V=(331.4+temp*0.607);        //由溫度計算速度值,單位是m/s
  243.     S=(uint)(time*V/2000);       //算出來是mm
  244.     if(flag_con2==1)                           //如果是連續測量,則取10次的平均值
  245.     {
  246.         if(k<=10)
  247.             k++;
  248.             if(k>=11)
  249.         k=1;
  250.             Sav[k]=S;
  251.             j++;
  252.             if(j<10)
  253.             S1=S;
  254.             if(j>=10)
  255.             {
  256.                 j=10;
  257.                 for(m=1;m<=10;m++)
  258.             totle=totle+Sav[m];
  259.             S1=(uint)(totle/10);              //取10次的平均值
  260.                 totle=0;
  261.         }
  262.     }
  263.     if(flag_one==1||flag_con1==1)          //如果是單次測量或連續瞬時測量,則取1次的值
  264.     {
  265.         S1=S;
  266.     }
  267. }

  268. void Delayus(uchar xus) //晶振為12MHz,延時時間為2i+5 us
  269. {
  270.     while(--xus);
  271. }

  272. bit Init_DS18B20(void)
  273. {
  274.         bit x;
  275.         DQ=1;
  276.         DQ=0;
  277.         Delayus(250);
  278.         DQ=1;
  279.         Delayus(20);
  280.         if(!DQ) x=0;
  281.         else x=1;
  282.         Delayus(250);
  283.         DQ=1;
  284.         return x;
  285. }

  286. //讀DS18B20函數
  287. uchar Read_DS18B20(void)
  288. {
  289.         uchar i=0,Dat=0;
  290.         for(i=0;i<8;i++)
  291.         {
  292.                 DQ=1;
  293.                 DQ=0;
  294.                 Dat>>=1;
  295.                 DQ=1;
  296.                 if(DQ) Dat |= 0x80;
  297.                 DQ=1;
  298.                 Delayus(30);
  299.         }
  300.         return Dat;
  301. }


  302. //寫DS18B20函數
  303. void Write_DS18B20(uchar Dat)
  304. {
  305.         uchar i=0;
  306.         for(i=0;i<8;i++)//循環8次,寫入一個字節
  307.         {
  308.                 DQ=1;//未發送前的狀態
  309.                 Dat >>= 1;//將要傳送的最低位放入CY
  310.                 DQ=0;//將總線拉低,產生寫時序
  311.                 DQ=CY;//將要傳送的位狀態送到總線上
  312.                 Delayus(30);//延時50us,即保持總線狀態,待DS18B20采樣
  313.                 DQ=1;//恢復期,總線置1
  314.         }
  315. }

  316. void GetTemp(void)       //獲取溫度函數
  317. {
  318.         uchar a=0,b=0;
  319.         Init_DS18B20();
  320.         Write_DS18B20(0xcc); //跳過ROM
  321.         Write_DS18B20(0x44); //開啟溫度轉換
  322.         Init_DS18B20();
  323.         Write_DS18B20(0xcc); //跳過ROM
  324.         Write_DS18B20(0xbe); //讀暫存器
  325.         a=Read_DS18B20();    //讀取高速暫存字節0,溫度低8位
  326.         b=Read_DS18B20();    //讀取高速暫存字節1,溫度高8位
  327.         temp=b;
  328.         temp<<=8;
  329.         temp=temp|a;         //將高、低位溫度編碼合在一起
  330.         if(b>=8)             //判斷溫度值是否為負,如果溫度高字節大于等于8說明溫度值為負
  331.         {
  332.             temp=~temp+1;      //將補碼轉換成原碼
  333.             Temp_Flag=1;       //溫度標志為1,表示溫度為負
  334.         }
  335.         else
  336.         {
  337.             Temp_Flag=0;       //溫度標志為0,表示溫度為正
  338.         }
  339.         temp=temp*0.0625+0.5;//將溫度編碼轉換成溫度值,加0.5是為了四舍五入
  340. }

  341. void CalcTestTemp()                              //溫度處理函數
  342. {
  343.         if(temp<100) Line1[2]=' ';        //如果溫度值小于10,十位顯示空白(不顯示0)
  344.         else Line1[2]=temp%100/10+0x30;   //取溫度十位并轉換成ASCII碼
  345.         Line1[3]=temp%10+0x30;            //取溫度個位并轉換成ASCII碼       
  346. }
復制代碼



Ultrasonic ranging.zip

41.3 KB, 下載次數: 147, 下載積分: 黑幣 -5

源代碼

評分

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

查看全部評分

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

使用道具 舉報

沙發
ID:89286 發表于 2017-7-7 05:17 | 只看該作者
thanks for sharing
回復

使用道具 舉報

板凳
ID:82765 發表于 2017-7-7 12:56 | 只看該作者
提示: 作者被禁止或刪除 內容自動屏蔽
回復

使用道具 舉報

地板
ID:152003 發表于 2017-7-7 21:50 | 只看該作者
好資料 不錯呢
回復

使用道具 舉報

5#
ID:1 發表于 2017-7-31 04:01 | 只看該作者
好資料,51黑有你更精彩!!!
回復

使用道具 舉報

6#
ID:223525 發表于 2017-8-1 16:23 | 只看該作者
不錯不錯
回復

使用道具 舉報

7#
ID:236761 發表于 2017-12-23 13:47 | 只看該作者

好資料,51黑有你更精彩!!!
回復

使用道具 舉報

8#
ID:88279 發表于 2018-3-3 22:10 來自手機 | 只看該作者
厲害。感謝分享!!!
回復

使用道具 舉報

9#
ID:300843 發表于 2018-4-5 23:31 | 只看該作者
感謝分享
回復

使用道具 舉報

10#
ID:493169 發表于 2019-3-20 11:54 | 只看該作者
感謝分享
回復

使用道具 舉報

11#
ID:156662 發表于 2019-3-20 13:38 | 只看該作者
感謝樓主無私奉獻
回復

使用道具 舉報

12#
ID:530187 發表于 2019-5-9 17:10 來自手機 | 只看該作者
程序好像不完全,flag_flow在哪里變化噠?
回復

使用道具 舉報

13#
ID:506687 發表于 2019-5-18 17:38 | 只看該作者
請問有原理圖嗎?
回復

使用道具 舉報

14#
ID:559822 發表于 2019-6-11 12:23 | 只看該作者
感謝分享 得好好琢磨琢磨
回復

使用道具 舉報

15#
ID:645965 發表于 2019-11-20 18:27 | 只看該作者
有實物連線圖嗎?
回復

使用道具 舉報

16#
ID:645965 發表于 2019-11-20 21:35 | 只看該作者
請問下那個lcd1602怎么連線,有點看不懂?
回復

使用道具 舉報

17#
ID:645965 發表于 2019-11-20 21:59 | 只看該作者
為什么1602的其余引腳沒有定義?
回復

使用道具 舉報

18#
ID:484092 發表于 2020-6-18 21:31 | 只看該作者
謝謝分享
。。。。。。。。。
回復

使用道具 舉報

19#
ID:484092 發表于 2020-6-18 21:31 | 只看該作者
邵曉杰 發表于 2019-11-20 21:59
為什么1602的其余引腳沒有定義?

定義了  p0口
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 综合第一页| 国产在线精品一区二区三区 | 羞羞的视频在线观看 | 日本一级淫片免费啪啪3 | 久久91精品久久久久久9鸭 | 久草资源在线 | 黄色av网站在线观看 | 国产一区二区毛片 | 国内精品视频一区二区三区 | 91婷婷韩国欧美一区二区 | 久久网亚洲 | 亚洲国产精品美女 | 免费毛片网站在线观看 | 操操网站 | 无码一区二区三区视频 | 久久精品免费一区二区三 | 精品国产一区二区三区日日嗨 | 自拍视频网站 | 免费看黄色片 | 日韩精品成人av | 欧美中国少妇xxx性高请视频 | 国产激情在线 | 日本成年免费网站 | 久色视频在线观看 | av手机免费在线观看 | 久久com| 日韩在线观看视频一区 | 操亚洲 | 日韩在线视频免费观看 | 一区二区免费看 | 国产成人精品一区二区三区在线 | 欧美二区在线 | 中文字幕成人 | 天天躁日日躁狠狠的躁天龙影院 | 免费视频99| 久久久久久久久淑女av国产精品 | 中文字幕一区二区三区精彩视频 | av第一页| 久国产 | 国产yw851.c免费观看网站 | 欧洲色|