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