|
本人喜歡制作超聲波測距儀,在網上看到了這款用CX20106做接收電路、單片機用AT89C52、顯示用若基亞手機3310LCD制作的超聲波測距儀,供電電壓DC5V,作者:babytaomail ,感覺制作的比較好,特此轉貼,讓多多的愛好者進行仿制。該超聲波測距儀測距范圍4.5cm~230cm,理論誤差可以達到2mm左右,資料比較齊全,很方便仿制。
#include "stdio.h"
#include "math.h"
#include "regx52.h"
#include "binary.h"
#include "intrins.h"
#define VOUT P3_7 //脈沖產生端口
#define DQ P1_0 //ds18b20 端口
/******************系統全局變量***************/
typedef unsigned char uchar;
typedef unsigned int uint;
bit Success; //測量成功標志位
bit Done; //測量完成標志位
bit Mode; //測量模式:0--近距離,1---遠距離
uint nCount;
uint nResult;
/******************18B20相關函數及變量***************/
bit SignedFlag=0; //符號標志位 ,負為1,正為0
uchar TempInt; //整數部分溫度
uint TempDot; //小數部分溫度
void ReadTemperature(void); //在程序中調用此函數
void Init_DS18B20(void);
unsigned char ReadOneChar(void);
void WriteOneChar(unsigned char dat);
void delayx(unsigned int i);
#include "18b20.h"
/******************LCD相關函數******************/
sbit SCLK = P2^0; // 串行時鐘
sbit SDIN = P2^1; // 串行數據輸入
sbit LCD_DC = P2^2; // 數據/命令 選擇端
sbit LCD_CE = P2^3; // 片選
sbit LCD_RST = P2^4; // 外部復位
#include "Nokia5110.c"
/***********超聲波測量相關函數定義***************/
void StartInit();
void Delay_us(uint i); //微秒級延時:T=7+2*(X-1) us
void StartMeasure();
void DisplayResult();
void ConvertCount();
void Delay_ms(uint x);
////////////////////////主函數////////////////////////////////
void main()
{
unsigned long Sum;
uchar i;
uchar num;
bit bOK;
uchar
TCON=B00000000; //INT0電平觸發
TMOD=0X01; //T0作為計數輸入
IP=B00000001; //置INT0優先級最高
LCD_init(); //液晶初始化
LCD_clear(); //清屏顯示
DisplayChinese(0,0,13,16,3,0,0,WORD); //在LCD上顯示“溫度:”
DisplayChinese(72,0,13,16,1,3,0,WORD); //在LCD上顯示“℃”
DisplayChinese(0,2,13,16,3,4,0,WORD); //在LCD上顯示"聲速:”
while(1) //測量系統主循環
{
bOK=0;
num=0;
Sum=0;
ReadTemperature(); //檢測當前環境溫度
for(i=1; i<=3; ++i) //循環測量,求平均值
{
StartInit(); //測量初始化
StartMeasure(); //開始測量第1次,確定大概范圍
if(Success==1)
{
bOK=1; //有1次成功,則測距成功
Sum=(nCount>Sum)?nCount:Sum; //取測量最大值
}
Delay_ms(80); //延時10ms后繼續測量
}
nCount=Sum;
Success=bOK;
DisplayResult();
}
}
/***************所用到的相關函數功能實現*****************/
void INT_0() interrupt 0 using 0 //運行到此處說明測距成功
{
TR0=0; //關計數
ET0=0; //關定時器中斷
EX0=0; //關INT0中斷
while(!P3_2); //等待CX20106輸出電平變高
//將計數器數據放進nCount,用來進行數據處理
nCount=TH0;
nCount=nCount<<8;
nCount|=TL0;
Success=1;
Done=1;
return;
}
void INT_T0() interrupt 1 using 1
{
//運行到此處說明測距失敗
TR0=0;
EX0=0;
Success=0;
Done=1;
return ;
}
void StartInit()
{
TH0=0;
TL0=0; //計數器置0
EA=1; //開總中斷
ET0=0; //關T0中斷
EX0=0; //關INT0中斷
Success=0; //測量成功標志位
Done=0; //測量一次標志位
}
void StartMeasure()
{
//產生脈沖波
uchar LOOP;
ET0=1;
for (LOOP = 0;LOOP < 4; )
{
P3 = P3 ^ 0x80;
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();//_nop_();_nop_();
LOOP++;
}
VOUT = 1;
TR0 = 1; //啟動計數器
if(Mode==0) //近距離測量模式
{
Delay_us(41); //50us延時測量,防止回波干擾
}
else //遠距離測量模式
{
Delay_us(300); //50us延時測量,防止回波干擾
}
EX0=1; //開INT0中斷
while(Done==0); //等待測量結束
}
void DisplayResult()
{
float temp=0;
char String[10];
//算出當前溫度
temp=TempInt+TempDot/10000.0;
//顯示當前溫度
sprintf(String,"%0.2f",temp);
DisplayEnglish(33,0,String);
//算出當前聲速
temp=332+0.607*temp;
//顯示當前聲速
sprintf(String,"%0.1fm",temp);
DisplayEnglish(33,2,String);
if(Success==1) //測距成功,顯示“成功”,并顯示距離
{
temp=nCount*temp/2000+0.5; // 算出距離
//顯示遠、近距離測量的結果
if(Mode==0)
{
nResult=(0.9723*temp-14.803)+0.5; //此式由擬合得到
DisplayEnglish(0,4,"N");
}
else
{
nResult=0.9648*temp-5.7716+0.5; //此式由擬合得到
DisplayEnglish(0,4,"F");
}
sprintf(String,"%5u cm",nResult); //將整數轉換為字符串
//拼湊顯示最終結果“xxx.xcm”
DisplayEnglish(8,4,String);
DisplayEnglish(40,4,".");
String[5]='\0';
DisplayEnglish(48,4,&String[4]);
Delay_ms(50);
}
else //測距失敗,顯示“失敗”提示
{
DisplayEnglish(0,4," --Fail-- ");
}
if(nResult>500)
{
Mode=1;
}
else
{
Mode=0;
}
}
void Delay_ms(uint x) //12M環境下延時1ms
{
uchar j;
while(x--)
{
for(j=0;j<125;j++);
}
}
void Delay_us(uint i) //微秒級延時:T=7+2*(X-1) us
{
while(--i);
}
|
|