#include<reg51.h>
#include<intrins.h>
#include<math.h>
#define uchar unsigned char
#define uint unsigned int
uchar code dispBUF[33]={"Temperature: Distance: mm "};
uchar numcode[10]={'0','1','2','3','4','5','6','7','8','9'};
uint num[29]={0};
uchar jsh,jsl; //计数器的高低位
uchar count=0; //10秒计次数
uint distance; //距离
uint temp; //温度变量
uchar bdata flag; //DS18B20存在标准
sbit RS=P2^0; //LCD RS
sbit RW=P2^1; //LCD RW
sbit E =P2^2; //LCD E
sbit DQ=P2^7; //DS18B20数字端口
sbit Busy = P0^7; //LCD 忙
void Delay(uint time);
void delay1ms(uint ms);
void delay();
void delay15(uchar us);
void BUMA(void);
void B20_WDAT(uchar dat);
uchar B20_RDAT(void);
void Init_18B20(void); //初始化18B20
void Write_Comm(uchar); //写入LCD命令
void Write_Data(uchar); //写入LCD数据
void Init_LCD(void);
sbit sta_flag =flag^0; //10MS到标准位,flag即通用标志位,当sta_flag=1时,表示到了10ms
sbit fuhao =flag^1; //温度的符号位
sbit START =P1^0; //启动测距
sbit CNT =P2^5; //发射超声波
sbit CSBIN =P2^6; //返回信号
sbit BUZZER =P3^7;
/******************定时器1溢出***************************/
void timer1(void)interrupt 2 using 1
{TR1=0;} //关闭定时器/计数器1
/*********定时器0溢出中断函数,每60MS溢出****************/
void timer0(void)interrupt 1 using 0 //定时器0
{
TH0=0x15;
TL0=0xA0; //定时器0设定初值
TH1=0;
TL1=0; //计数器1清零
sta_flag=1;
count++;
_nop_();
_nop_();
_nop_();
_nop_();
CNT=1; //先延时,后开始发送40KHz的超声波
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_(); //40KHZ的倒数就是25us,12个_nop_();就是24us
CNT=0; //保持一段时间高电平
_nop_();
_nop_();
_nop_();
_nop_();
TR1=1; //延时,避免直达信号干扰,启动定时器/计数器1
delay15(50); //延时避开直达信号
}
/***************系统初始化*************************/
void SYS_INIT()
{
uchar i;
for(i=0;i<29;i++) //显示清零
{ num[i]=0;}
TMOD=0x11; //工作方式寄存器TMOD,设置定时器/计数器0和1均为16位定时/计数器
TH0 =0x15;
TL0 =0xA0; //设置定时器/计数器0的初值,60ms溢出
P0 =0;
CNT=0; //P2^5口,发射发射超声波
CSBIN=1; //P2^6口,接收信号
EA =1; //开总中断
}
/******************距离计算***************************/
void JULIJS() //使用全局变量,可以定义为空
{
float c,d,s;
uint t;
if(temp<0x8000)
c=331.4+0.61*temp*0.0625;
else //温度为负
c=331.4-0.61*temp*0.0625;
t=jsh*256+jsl-120; //计算计数值
d=(c*t*0.001)/2;
d*=d;
s=d-7.98;
distance=sqrt(s); //修正后的值,数据通过全局变量distance传输
}
/****************转换成2进制***************/
void HEXtoBCD()
{
float tp;
unsigned long int tmp;
fuhao=0; //温度符号位
if(temp<0x8000)
tp=temp*0.0625;
else //温度为负,则求补码得到原码
{
BUMA();
tp=temp*0.0625;
fuhao=1;
}
tp*=10;
tmp=tp;
num[12]=tmp/100; //数据转换后放到显示数组里面
if(fuhao)
num[12]=num[12]|0x80; //最高位加上符号位
num[13]=tmp/10-(tmp/100)*10;
tmp=distance;
num[25]=tmp/1000;
tmp%=1000;
num[26]=tmp/100;
tmp%=100;
num[27]=tmp/10;
tmp%=10;
num[28]=tmp/1;
}
/**************温度转换函数***************************/
void TESTTEMP()
{
Init_18B20(); //初始化18B20
if(flag)
{
B20_WDAT(0xCC); // 跳过读序号列号的操作,忽略ROM匹配
B20_WDAT(0x44); // 发送温度转化命令
}
}
/***********读取温度函数**************/
uint GET_WD(void)
{
uint a = 0, b = 0, t = 0;
Init_18B20(); //初始化18B20
B20_WDAT(0xCC); //跳过读序号列号的操作
B20_WDAT(0xBE); //发送读温度命令
a = B20_RDAT();
b = B20_RDAT(); //读取一个字节(读出高8位和低8位)
t = b;
t <<= 8;
t = t | a; //字节合并
return (t); //返回结果给调用
}
/***************18B20复位函数***********************/
void Init_18B20()
{
DQ = 1; //DQ复位
Delay(10);
DQ = 0; //单片机将DQ拉低
Delay(80); //480us
DQ = 1; //拉高总线
Delay(10); //稍做延时后 如果x=0则初始化成功,x=1则初始化失败
if(DQ)
flag=0;
else
flag=1;
Delay(20);
}
/*******************读数据******************************/
uchar B20_RDAT(void) //读取一个字节
{
uchar i = 0;
uchar dat = 0;
for (i = 8; i > 0; i--)
{
DQ = 0; // 拉低数据线,开始读数据
dat >>= 1;
DQ = 1; // 拉高数据线,停止读数据
if(DQ)
dat |= 0x80; //拼装处理
Delay(15);
}
return (dat); //注意读取的为补码
}
/*********************写数据****************************/
void B20_WDAT(uchar dat)
{
uchar i = 0;
for (i = 8; i > 0; i--)
{
DQ = 0; //拉低数据线至少15us以作为起始信号
DQ = dat&0x01; //取出低位的一位数据
Delay(5); //稍作延时
DQ = 1; //将数据线拉高以作为停止信号
dat>>=1; //移位,为写入下一位数据做准备
}
}
/*******************数据转换函数**************************/
void BUMA()
{
temp=~temp; //按位取反
temp+=1;
}
/**************************LCD显示函数*******************/
void LCD_DISP()
{
uchar a,b,d;
Init_LCD();
Write_Comm(0x01); //清显示
Write_Comm(0x80); //写首地址
for(a=0;a<16;a++)
{
d=dispBUF[a];
if((a>11)&&(a<14)) //如果是结果位到num[]里面读取
{
d=numcode[num[a]]; //待显示的结果
}
if(14==a)
{
d=0xdf;
}
Write_Data(d); //写入要显示的数据
}
Write_Comm(0xc0); //换行,换到第二行
for(b=16;b<33;b++)
{
d=dispBUF[b];
if((b>24)&&(b<29))
{
d=numcode[num[b]];
}
Write_Data(d); //写入要显示的数据(数据传输)
}
}
/*********检查LCD忙状态***********/
bit LCD_BUSY() //lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令。
{
bit BS;
RW = 1;
RS = 0;
E = 1;
delay1ms(1);
BS =(bit)(P0&0x80);
E = 0;
return BS;
}
/*******************写指令函数******************************/
void Write_Comm(uchar lcdcomm) //写指令
{
while(LCD_BUSY());
RS = 0;
RW = 0;
E = 1;
delay1ms(1);
P0= lcdcomm;
delay1ms(1);
E = 0;
}
/*********************写数据函数****************************/
void Write_Data(uchar lcddata)//写数据
{
while(LCD_BUSY());
RS = 1;
RW = 0;
E = 1;
delay1ms(1);
P0= lcddata;
delay1ms(1); //判断是否忙状态
E = 0;
}
/*********************初始化LCD*********