#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit Trig =P1^0;
sbit Echo =P3^2;
sbit test =P1^1; //测试灯引脚
sbit dula =P2^6; //段码选通引脚
sbit wela =P2^7; //位码选通引脚
sbit DS =P2^2; //测温引脚
uchar code table[]={0xfc,0x60,0xda,0xf2,
0x66,0xb6,0xbe,0xe0,0xfe,0xf6};
uchar code table1[]={0xfd,0x61,0xdb,0xf3,
0x67,0xb7,0xbf,0xe1,0xff,0xf7};
uchar flag,outcomeH,outcomeL;
bit succeed_flag;
void delay(uint count) //延时程序
{
uint i;
while(count)
{
i=200;
while(i>0)
i--;
count--;
}
}
void delay_20us() //延时20us
{ uchar bt ;
for(bt=0;bt<100;bt++);
}
void display(uint distance_date) //距离显示子程序
{
uchar dm,cm,mm;
dm=distance_date/100; //计算分米位
cm=distance_date%100/10; //计算厘米位
mm=distance_date%10; //计算毫米位
dula=0;
P0=table[dm];
dula=1;
dula=0;
wela=0;
P0=0x7f;
wela=1;
wela=0;
delay(2);
dula=0;
P0=table1[cm];
dula=1;
dula=0;
wela=0;
P0=0xbf;
wela=1;
wela=0;
delay(2);
P0=table[mm];
dula=1;
dula=0;
P0=0xdf;
wela=1;
wela=0;
delay(2);
}
void dsreset(void) //send reset and initialization command
{
uint i;
DS=0;
i=103;
while(i>0)i--;
DS=1;
i=4;
while(i>0)i--;
}
bit tmpreadbit(void) //read a bit
{
uint i;
bit dat;
DS=0;i++; //i++ for delay
DS=1;i++;i++;
dat=DS;
i=8;while(i>0)i--;
return (dat);
}
uchar tmpread(void) //read a byte date
{
uchar i,j,dat;
dat=0;
for(i=1;i<=8;i++)
{
j=tmpreadbit();
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
return(dat);
}
void tmpwritebyte(uchar dat) //write a byte to ds18b20
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //write 1
{
DS=0;
i++;i++;
DS=1;
i=8;while(i>0)i--;
}
else
{
DS=0; //write 0
i=8;while(i>0)i--;
DS=1;
i++;i++;
}
}
}
void tmpchange(void) //DS18B20 begin change
{
dsreset();
delay(1);
tmpwritebyte(0xcc); // address all drivers on bus
tmpwritebyte(0x44); // initiates a single temperature conversion
}
uint tmp() //get the temperature
{
float tt;
uchar a,b;
dsreset();
delay(1);
tmpwritebyte(0xcc);
tmpwritebyte(0xbe);
a=tmpread();
b=tmpread();
temp=b;
temp<<=8; //two byte compose a int variable
temp=temp|a;
tt=temp*0.0625;
temp=tt*10+0.5;
return temp;
}
void readrom() //read the serial
{
uchar sn1,sn2;
dsreset();
delay(1);
tmpwritebyte(0x33);
sn1=tmpread();
sn2=tmpread();
}
void main(void)
{
uint distance_data;
uchar a;
float tem;
flag=0; //标志位,1表示收到回波,0则未收到
test=0; //控制灯闪烁
Trig=0;
TMOD=0x11; //对定时器1选择16位模式
IT0=0; //设置触发方式为低电平触发
IE0=0;
EA=1; //开总中断
tmpchange(); //测出当时温度
ET0=0;
TR0=0;
while(1)
{
EA=0;
TH1=0;
TL1=0;
Trig=1; //让TRIG引脚为高电平
delay_20us(); //延时20us
Trig=0; //产生方波
while(Echo==0); //等待Echo变为低电平,即开始发射超声波
TR1=1; //开始计时
succeed_flag=0;
EX0=1;
TF1=0;
EA=1;
while((TH1<25)&&(!IE0)); //等待25us或者中断产生(即收到回波)
TR1=0; //停止计时
EX0=0; //关闭中断
if(succeed_flag==1) //如果收到回波
{
distance_data=outcomeH; //先保存高8位
distance_data<<=8; //将高8位左移,第八位则全置0
distance_data=distance_data|outcomeL; //将高低八位组成新的16位数据
tem=tmp(); //取得温度
tem/=10;
tem=331.5+0.607*tem; //得出当前波速
tem/=2000;
distance_data*=tem;
distance_data=distance_data*126000/120000; //代入晶振频率及当前波速算出距离
for(a=300;a>0;a--)
{
display(distance_data); //显示距离
}
}
if(succeed_flag==0) //如果没有收到回波
{
distance_data=0;
test = !test;
}
}
}
INTO_() interrupt 0 //外部中断0
{
outcomeH =TH1;
outcomeL =TL1;
succeed_flag=1;
EX0=0;
}