本代碼基于QH - 5A平臺,測試通過,適用于51系列單片機平臺,不同的型號只需要移植一下即可,SR04超聲波模塊是一個精度較高的測距模塊,本人測試精度1cm,模塊可直接與開發板連接,具體連接請參考本貼下面的內容,連接模塊時一定要斷電連接,不要帶電操作,容易損壞并且工作可能不正常。模塊實物如下圖所示:

開發板圖片:
2015-10-11 192246.jpg (196.58 KB, 下載次數: 97)
下載附件
2017-9-5 08:13 上傳
1、SR04模塊主要技術參數:
1.使用電壓:DC5V
2.靜態電流:小于2mA
3:電平輸出:高5V
4:電平輸出:低0V
5:感應角度:不大于15度
6:探測距離:2cm-450cm
7:高精度:可達3mm
2、接線方式:VCC、trig(控制端)、 echo(接收端)、 GND地線(若采用QH-5A開發板直接插上即可)
3、使用方法: 一個控制口trig發一個10US以上的高電平,就可以在接收口echo等待高電平輸出.一有輸出就可以開定時器計時,當echo此口變為低電平時就可以讀定時器的值,此時就為此次測距的時間,方可算出距離.如此不斷的周期測,就可以達到你移動測量的值了~~
4、模塊工作原理:
(1)采用IO觸發測距,給至少10us的高電平信號;
(2)模塊自動發送8個40khz的方波,自動檢測是否有信號返回;
(3)有信號返回,通過IO輸出一高電平,高電平持續的時間就是超聲波從發射到返回的時間.測試距離=(高電平時間*聲速(340M/S))/2或距離=(331.4+0.61*當前溫度)*定時器時間/2000000 CM;
5、程序功能:
本程序是采用第二公式編寫的,顯然有溫度矯正的超聲波測距更加準確,同時本程序還帶有內部存儲功能,可設定報警距離,程序有詳細注釋
水平有限,本程序只供學習,歡迎大家一起交流
單片機源程序如下:
- /*-----------------------------------------------
- 說明:
- 功能:超聲波測距,DS18b20矯正;數碼管顯示
- 晶振:12MHz
- 測量范圍:1CM - 500CM
- 溫度顯示:0.0 C - 99.9 C
- 警報范圍設置:5CM - 400CM(可以永久存儲設定值)
- ------------------------------------------------*/
- #include "reg52.h" //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義
- #include "18b20.h"
- #include "eeprom.h"
- #include "delay.h"
- #define DataPort P0 //定義數據端口 程序中遇到DataPort 則用P1 替換
- sbit DUAN=P2^6;//定義鎖存使能端口 段鎖存
- sbit WEI=P2^7;// 位鎖存
- /***************超聲波引腳定義******************/
- sbit Echo = P3 ^ 3; //回波引腳
- sbit Trig = P1 ^ 5; //觸發引腳
- sbit buzzer = P1 ^ 0; //蜂鳴器引腳
- /*****************按鍵定義**********************/
- uchar bdata key,key1,lastkey;
- bit key1Mark;//設置鍵標志
- /*****************測距變量**********************/
- uchar EchoTimeH,EchoTimeL; //自定義寄存器存儲8位回波時間
- uint Distance,EchoTime; //測量距離,回波總時間
- uint Distance_Alarm; //報警距離通過自己設定(初始為0)
- bit succeed_flag; //測量成功標志
- uchar code Table[18] = //段碼表
- {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 顯示段碼值0~9
- uchar code WeiMa[4]={0xfe,0xfd,0xfb,0xf7}; //分別對應相應的數碼管點亮,即位碼
- uint Temperature,temp;//讀取溫度
- bit flag200ms,flag300ms;//獲取時間標志
- /*****************顯示變量**********************/
- uint DispData;
- uchar TempData[4]; //存儲顯示值的全局變量
- uchar mod;//顯示模式切換
- /*****************函數聲明**********************/
- void delay_20us(); //20us延遲
- void CountDat(uint ShowData); //顯示數據處理
- void readkey(); //按鍵讀取
- void CountKey(); //顯示散轉
- void CSBFunction(); //超聲波測距
- void Display(); //數碼管顯示函數
- void Init_Timer0(void); //定時器0初始化
- /*------------------------------------------------
- 主函數
- ------------------------------------------------*/
- void main (void)
- {
- float speed = 0;
- buzzer=1; //初始化蜂鳴器引腳
- Trig=0; //首先拉低脈沖輸入引腳
- TMOD|=0x11; //定時器0,定時器1,16位工作方式
- IT1=0; //低電平觸發外部中斷
- EX1=0; //關閉外部中斷
- Init_Timer0();
- ISP_IAP_readData(0x2ff0,ReadBuf,2);
- Distance_Alarm = ReadBuf[0] | (ReadBuf[1] << 8);//讀取警報距離值
- while (1) //主循環
- {
- CSBFunction(); //開始測距
- if(succeed_flag)
- {
- succeed_flag=0; //清測量成功標志
- EchoTime = (EchoTimeH << 8) | EchoTimeL; //與低8位合并成為16位結果數據
- //公式說明: 1、V=(331.4+0.61*T)*D/2000000 CM;2、回波時間D是us單位,最終
- //距離以CM單位要除以20000,這里為了減小計算量轉成uchar,先/200,再/100;
- speed = (331.4 + 0.61 * (TempData[0]*10+TempData[1])) / 200;
- Distance = (EchoTime * speed) / 100; //算出來是CM
- CountDat(DispData);//計算需要顯示數據的各個位
- }
- if(mod != 2)
- readkey();//按鍵讀取,警報時顯示溫度不能設定
- CountKey();//報警距離設置
- if(flag200ms)
- {
- flag200ms = 0;
- temp = ReadTemperature();//
- Temperature = temp * 6;//小數近似處理,采用中間變量temp是防止中斷導致最終溫度值異常
- if(Distance < Distance_Alarm)
- {
- buzzer = 0;mod = 2;
- }
- else
- {
- buzzer = 1;
- if(!key1Mark)
- mod = 0;
- }
- } //蜂鳴器產生300Hz頻率
- if(flag300ms)
- {
- flag300ms = 0;
- if(Distance < Distance_Alarm)
- {
- buzzer = 1;
- }
- }
- }
- }
- /*------------------------------------------------
-
- 顯示函數,用于動態掃描數碼管
- ------------------------------------------------*/
- void Display()
- {
- static unsigned char i=0;
- DataPort=0; //清空數據,防止有交替重影
- DUAN=1; //段鎖存
- DUAN=0;
-
- DataPort=WeiMa[i]; //取位碼
- WEI=1; //位鎖存
- WEI=0;
- if((i == 1) && (mod == 2))
- {
- DataPort = Table[TempData[i]] & 0xef;//溫度顯示點
- }
- else
- {
- DataPort = Table[TempData[i]] ; //取顯示數據,段碼
- }
- DUAN=1; //段鎖存
- DUAN=0;
-
- i ++;
- if(i == 4)
- i = 0;
- }
- //******************************************************************
- //20us短延時
- void delay_20us()
- {
- uchar bt;
- for(bt=0;bt<20;bt++);
- }
- /*
- 處理需要顯示的數據
- 入口參數:ShowData
- */
- void CountDat(uint ShowData)
- {
- EA=0;
- TempData[0] = ShowData / 1000 % 10;
- TempData[1] = ShowData / 100 % 10;
- TempData[2] = ShowData / 10 % 10;
- TempData[3] = ShowData % 10;
- EA=1;
- }
- /*掃描K1 - K3*/
- void readkey()
- {
- static uchar keycnt = 0;
- uchar R0,R1;
- P3 |= 0x07; //51單片機作為輸入時先置相應位位1
- R0 = (P3 ^ 0x07) & 0x07; //將鍵值轉換成正邏輯
- keycnt ++;
- if(R0)
- {
- if(keycnt > 1) //用做延遲,根據MCU速度進行調整
- {
- keycnt = 0;
- key1 = R0;
- }
- else
- {
- key1 = key;
- }
- }
- else
- {
- key1 = 0; //無按鍵按下都為0
- keycnt = 0;
- }
- R1 = key1;
- key1 = key1 & (key ^ key1);//key^key1判斷鍵值有0變1,或1變0;再&key1若key1不為0則有按鍵按下(由0變1)
- key = R1;
- }
- /*讀取按鍵后,根據鍵值處理數據*/
- void CountKey()
- {
- switch(key1)
- {
- case 0x01:if(!key1Mark){mod = 1;key1Mark = 1;}
- else
- {
- mod = 0;key1Mark = 0;
- WriteBuf[0] = Distance_Alarm & 0xff; WriteBuf[1] = (Distance_Alarm >> 8) & 0xff;
- ISP_IAP_sectorErase(0x2e00);//扇區擦除,一塊512字節
- ISP_IAP_writeData(0x2ff0,WriteBuf,2); //寫警報值到 EEPROM
- }
- break;
- case 0x02:if(mod == 1){Distance_Alarm += 5;if(Distance_Alarm > 400)Distance_Alarm=400;}
- break;
- case 0x04:if(mod == 1){Distance_Alarm -= 5;if(Distance_Alarm < 5)Distance_Alarm=5;}
- break;
- default : break;
- }
- switch(0) //數據顯示模式散轉
- {
- case 0:DispData = Distance; //正常默認下顯示測得的距離
- break;
- case 1:DispData = Distance_Alarm; //設置模式下顯示警報距離
- break;
- case 2:DispData = Temperature; //警報下顯示當前溫度值
- break;
- default : break;
- }
- }
- /*超聲波測距*/
- void CSBFunction()
- {
- EA=0;
- Trig=1;
- delay_20us();
- Trig=0; //產生一個20us的脈沖,在Trig引腳
- while(Echo==0); //等待Echo回波引腳變高電平,高電平持續的時間就是超聲波從發射到返回的時間
- {
- EX1=1; //打開外部中斷
- TH1=0; //定時器1清零
- TL1=0; //定時器1清零
- TF1=0;
- TR1=1; //啟動定時器1
- EA=1;
- }
- while(TH1 < 255);//等待測量的結果,周期65.535毫秒(可用中斷實現),在這段時間內等待外部中斷
- {
- TR1=0; //關閉定時器1
- EX1=0; //關閉外部中斷
- }
- }
- /*------------------------------------------------
- 定時器初始化子程序
- ------------------------------------------------*/
- void Init_Timer0(void)
- {
- TMOD |= 0x01; //使用模式1,16位定時器,使用"|"符號可以在使用多個定時器時不受影響
- TH0=(65536-2000)/256; //給定初值 2ms
- TL0=(65536-2000)%256;
- EA=1; //總中斷打開
- ET0=1; //定時器中斷打開
- TR0=1; //定時器開關打開
- }
- /*------------------------------------------------
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
eeprom超聲波.rar
(57.28 KB, 下載次數: 41)
2017-9-5 09:13 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|