超聲波單片機源程序如下:
- /*-----------------------------------------------
- 說明:
- 功能:超聲波測距,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; //定時器開關打開
- }
- /*------------------------------------------------
- 定時器中斷子程序
- ------------------------------------------------*/
- void Timer0_isr(void) interrupt 1
- {
- static unsigned char Cnt200ms,Cnt300ms;
- TH0=(65536-2000)/256; //重新賦值 2ms
- TL0=(65536-2000)%256;
- Display(); // 調用數碼管掃描
- Cnt200ms ++;
- if(Cnt200ms == 100)
- {
- Cnt200ms = 0;
- flag200ms = 1;
- Cnt300ms ++;
- if(Cnt300ms == 3)
- {
- Cnt300ms = 0;
- flag300ms = 1;
- }
- }
- }
- //***************************************************************
- //外部中斷1,用做判斷回波電平,低電平引發中斷,得到高電平的持續時間
- INT1_() interrupt 2 // 外部中斷
- {
- EchoTimeH = TH1; //取出定時器的值
- EchoTimeL = TL1; //取出定時器的值
- succeed_flag = 1; //置成功測量的標志
- EX1=0; //關閉外部中斷
- }
復制代碼
所有資料51hei提供下載:
eeprom超聲波.rar
(57.28 KB, 下載次數: 15)
2018-11-11 16:10 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|