基于51的超声波测距代码+原理图(含温度补偿)
【代码】基于51的超声波测距代码+原理图(含温度补偿)
·
代码:
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit Trig = P1^7; //超声波发送信号
sbit Echo = P3^2; //超声波接收信号
bit timeout_flag = 0; //接收超时标志,距离过长或超声波未响应
sbit DQ = P3^0; //温度传感器
sbit BUZZER = P3^7; //蜂鸣器
sbit Key0 = P3^3; //不加温度补偿自锁开关
sbit Key1 = P3^4; //加温度补偿自锁开关
sbit LED0 = P3^5;
sbit LED1 = P3^6;
void bcd(uint setdata);
void display(uint setdata); //显示距离d(distance)
void delayms(uint t);
void delayus(uint us);
void Get_distance_Data();
uint diatance_Conut();
uint DS18B20_init();
void write_byte(uchar dat);
uchar read_byte();
uint read_temper();
uint temper_change();
float time; //超声波传播时间
float distance = 9999;//显示9999或0(其实达不到2mm,软件仿真最小只有30mm)即为超出范围
float Temperature = 25;
uchar num1[4]; //储存四位数字
uchar code ledval[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
uchar code ledpoint[]={0xf1,0xf2,0xf4,0xf8};
void main()
{
LED0 = 1;
LED1 = 1;
BUZZER = 0;
TMOD = 0X11;
TH0 = 0;
TL0 = 0;
ET0 = 1; //允许T0中断
EA = 1;
DS18B20_init();
while(1)
{
Get_distance_Data();
distance = diatance_Conut();
display((int)distance);
// display((int)temper_change());
}
}
void Get_distance_Data()
{
Trig = 1;
delayus(22);
Trig = 0;
Trig = 1;
delayus(22);
Trig = 0;
while(!Echo);
TR0 = 1;
while(Echo);
TR0 = 0;
}
uint diatance_Conut()
{
uint S;
time = TH0*256+TL0;
TH0 = 0;
TL0 = 0;
if(Key1 == 1 && Key1 == 1)
{
S = 9999;
LED0 = 1;
LED1 = 1;
BUZZER = 0;
}
if(Key0 == 0 && Key1 == 1)
{
S = (time*0.34)/2.0; //温度补偿前,显示为mm
LED0 = 0;
LED1 = 1;
}
if(Key1 == 0 && Key0 == 1)
{
Temperature = temper_change();
S = (331.45+0.61*Temperature)*time/2000; //温度补偿后,显示为mm
LED0 = 1;
LED1 = 0;
}
if(Key1 == 0 || Key0 == 0)
{
BUZZER = 0;
if(S>=3000)
{
S = 9999;
BUZZER = 1;
}
if(S<=2)
{
S = 0;
BUZZER = 1;
}
if(timeout_flag == 1)
{
S = 9999;
BUZZER = 1;
timeout_flag = 0;
TH0 = 0;
TL0 = 0;
}
}
return S;
}
void timer0mode1() interrupt 1
{
timeout_flag = 1;
}
void display(uint setdata)
{
uchar i;
bcd(setdata);
for(i=0;i<4;i++)
{
P2=ledpoint[i]; //数码管位选
P0=ledval[num1[i]]; //数码管段选
delayms(2);
}
}
void bcd(uint setdata)
{
num1[0]=setdata/1000;
num1[1]=(setdata%1000)/100;
num1[2]=((setdata%1000)%100)/10;
num1[3]=((setdata%1000)%100)%10;
}
//ms级延时
void delayms(uint t)
{
uchar i;
while(t--)
{
for(i=0;i<120;i++)
{;}
}
}
//us级延时
void delayus(uint us)
{
while(us--);
}
uint DS18B20_init()
{
uchar i;
DQ=1;
delayus(1); //稍作延时
DQ=0;
delayus(80); //延时480到960us
DQ=1;
i = 0;
while(DQ) //等待DS18B20拉低总线
{
delayms(1);
i++;
if(i>5)//约等待>5MS
{
return 0;//初始化失败
}
}
return 1;
}
void write_byte(uchar dat) //写一个字节
{
uchar i;
for(i=0;i<8;i++)
{
DQ=0; //每写入一位数据之前先把总线拉低1us
_nop_();
DQ=dat&0x01; //取最低位写入
delayus(10); //延时68us,持续时间最少60us
DQ=1; //然后释放总线
dat=dat>>1; //从低位开始写
}
delayus(10);
}
uchar read_byte() //读一个字节
{
uchar i,dat=0, bi;
for(i=0;i<8;i++)
{
DQ=0; //先将总线拉低1us
_nop_();
DQ=1; //然后释放总线
_nop_();
_nop_();
_nop_();
_nop_();
// if(DQ) dat=dat|0x80; //每次读一位
// dat=dat>>1; //从最低位开始读
bi = DQ;
dat = (dat >> 1)|(bi << 7);
delayus(10); //读取完之后等待48us再接着读取下一个数
}
return dat;
}
uint read_temper()
{
uchar a,b;
uint t=0;
DS18B20_init();
delayms(1);
write_byte(0xcc); //跳过ROM操作命令
write_byte(0x44); //发送启动温度转换命令
DS18B20_init();
delayms(1);
write_byte(0xcc); //跳过ROM操作命令
write_byte(0xbe); //发送读温度寄存器命令
a=read_byte(); //先读低八位
b=read_byte(); //再读高八位
t=b;
t<<=8; //左移八位
t=t|a; //t为16位的数,使高八位为b的值,低八位为a的值
return t; //返回温度值
}
uint temper_change()
{
int temper;
float tp;
temper=read_temper();
if(temper<0) //考虑负温度的情况
{
temper=temper-1;
temper=~temper;
tp=temper*0.0625; //16位温度转换成10进制的温度
temper=tp+0.5; //四舍五入
}
else
{
tp=temper*0.0625; //16位温度转换成10进制的温度
temper=tp+0.5; //四舍五入
}
return temper;
}
原理图:
更多推荐
所有评论(0)