/**********************************************
程序名称:DS18B20应用程序,LCD1602显示
简要说明:DS18B20测温驱动,同时可以测出所使用的DS18B20的序列号
程序作者:1986zhaofeng <1986zhaofeng@163.com>
**********************************************/
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
//定义1602指令集//
#define CMD_clear 0x01 // 清除屏幕
#define CMD_back 0x02 // DDRAM回零位,数据指针清零
#define CMD_dec1 0x04 // 读入后AC(指针)减1,向左写
#define CMD_add1 0x06 // 读入后AC(指针)加1,向右写
#define CMD_dis_gb1 0x0f // 开显示_开光标_开光标闪烁
#define CMD_dis_gb2 0x0e // 开显示_开光标_关光标闪烁
#define CMD_dis_gb3 0x0c // 开显示_关光标_关光标闪烁
#define CMD_OFF_dis 0x08 // 关显示_关光标_关光标闪烁
sbit DQ= P2^0;
sbit lcden=P3^4;
sbit rs=P3^5;
uchar fCode[8];
uchar flg;
uchar num;
void delay(uint z)
{
uint x,y;
for (x=z;x>0;x--)
for(y=110;y>0;y--);
}
void w_com(uchar com)
{
rs=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void w_data(uchar date)
{
rs=1;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()
{
lcden=0;
w_com(0x38);
w_com(CMD_dis_gb3);
w_com(0x06);
w_com(0x01);
w_com(0x80);
}
void print(uchar a,uchar *str){
w_com(a);
while(*str != '\0'){
w_data(*str++);
}
*str = 0;
}
void print2(uchar a,uchar t){//设置写入地址和数据//
w_com(a);
w_data(t);
}
//===============================DS18B20驱动==============================//
// 定义DS18B20数据线
/**************************************************************************/
void Delay1(int num)//延时函数.
{
while(num--) ; //对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于为8us
}
/**************************************************************************/
void Init_DS18B20(void)//初始化ds1820
{
unsigned char x=0;
DQ = 1; //DQ复位
Delay1(8); //稍做延时
DQ = 0; //单片机将DQ拉低
Delay1(80); //精确延时 大于 480us
DQ = 1; //拉高总线
Delay1(14);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失 ,
Delay1(20);
}
/**************************************************************************/
unsigned char ReadOneChar(void)//读一个字节
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
Delay1(4);
}
return(dat);
}
/**************************************************************************/
void WriteOneChar(unsigned char dat)//写一个字节
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
Delay1(5);
DQ = 1;
dat>>=1;
}
}
/**************************************************************************/
unsigned int ReadTemperature(void)//读取温度
{
unsigned char a=0;
unsigned char b=0;
int t=0;
float tt=0;
flg=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器
//连续读取两个字节数据
a=ReadOneChar(); //读低8位
b=ReadOneChar(); //读高8位
//将高低两个字节合成一个整形变量
//计算机中对于负数是利用补码来表示的
t=b;
t<<=8;
t=t|a;
//若是负值, 读取出来的数值是用补码表示的
if(b&0x80)
{
flg=1;
t=(~t+1);
}
//使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读 回数据的最低位代表0.0625度
tt=t*0.0625;
t= tt*10+0.5; //放大10倍输出并四舍五入
return(t);
}
/**************************************************************************/
void printTemperature(void){//写一个字节
int i=0;
unsigned char a=0,b=0,c=0;
i=ReadTemperature();//读温度并送显
print2(0x80,' ');
if(flg)
print2(0x80,'-');
a=i/100;
if(a > 0x09){
print(0x81,"--.-");
}else
{
print2(0x81,a+0x30); //显示温度十位
b=i/10-a*10;
print2(0x82,b+0x30); //个位
print(0x83,"."); //"."
c=i-a*100-b*10;
print2(0x84,c+0x30); //小位1位
}
print2(0x85,0xdf); //度C
print2(0x86,0x43);
}
/**********************************************************
*系列号显示子程序
*显示顺序(从左到右)8位CRC编码->48位序列号->8位产品系列编码
**********************************************************/
void DispCode()
{
unsigned char i,temp;
w_com(0x80+0x40);
for (i=8;i>0;i--)
{
//显示高4位
temp = fCode[i-1]>>4;
if (temp<10) //ASCII码转换
w_data(temp += 0x30);
else
w_data(temp += 0x37);
//显示低4位
temp = fCode[i-1]&0x0f;
if (temp<10) //ASCII码转换
w_data(temp += 0x30);
else
w_data(temp += 0x37);
}
}
void main()
{ uchar i;
init();
Init_DS18B20();
WriteOneChar(0x33);
for (i=0;i<8;i++)
{//读取64位系列号
fCode[i] = ReadOneChar();
}
Init_DS18B20();
DispCode();
while(1)
{
printTemperature();
}
}