|
本人喜欢制作超声波测距仪,在网上看到了这款用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);
}
|
|