//-------------------------------------------------------------------------------------------------
//名称:DS18B20温度传感器实验
//-------------------------------------------------------------------------------------------------
//说明:运行本例时,外界温度将显示在1602LCD上
//-------------------------------------------------------------------------------------------------
#include<reg51.h>
#include<intrins.h>
#include<LCD1602.h>
#define uchar unsigned char
#define uint unsigned int
#define delayNOP() {_nop_(); _nop_(); _nop_(); _nop_();}
sbit DQ=P2^6;
uchar code Temp_Disp_Title[]={" Current Temp : "};
uchar xdata Current_Temp_Display_Buffer[]={" TEMP: "};
uchar code Temperature_Char[8]={0x0c,0x12,0x12,0x0c,0x00,0x00,0x00,0x00}; //温度字符
uchar code df_Table[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9}; //温度小数位对照表
uchar CurrentT=0; //当前读取的温度整数部分
uchar Temp_Value[]={0x00,0x00}; //从DS18B20读取的温度值
uchar Display_Digit[]={0,0,0,0}; //待显示的各温度数位
uint DS18B20_IS_OK=1; //传感器正常标志
//-------------------------------------------------------------------------------------------------
//延时
//-------------------------------------------------------------------------------------------------
void DelayXus(uint x)
{
uchar i;
while(x--) for(i=0;i<200;i++);
}
//-------------------------------------------------------------------------------------------------
//延时2
//-------------------------------------------------------------------------------------------------
void Delay(uint x)
{
while(--x);
}
//-------------------------------------------------------------------------------------------------
//初始化DS18B20
//-------------------------------------------------------------------------------------------------
uchar Init_DS18B20()
{
uchar status;
DQ=1; Delay(8); DQ=0; Delay(90); DQ=1; Delay(8);
status=DQ; Delay(100);
DQ=1;
return status;
}
//-------------------------------------------------------------------------------------------------
//读一字节
//-------------------------------------------------------------------------------------------------
uchar ReadOneByte()
{
uchar i,dat=0;
DQ=1; _nop_();
for(i=0;i<8;i++)
{
DQ=0; dat>>=1; DQ=1; _nop_(); _nop_();
if(DQ) dat|=0x80;
Delay(30);
DQ=1;
}
return dat;
}
//-------------------------------------------------------------------------------------------------
//写一字节
//-------------------------------------------------------------------------------------------------
void WriteOneByte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DQ=0; DQ=dat&0x01; Delay(5); DQ=1; dat>>=1;
}
}
//-------------------------------------------------------------------------------------------------
//读取温度值
//-------------------------------------------------------------------------------------------------
void Read_Temperature()
{
if(Init_DS18B20()==1) //DS18B20故障
DS18B20_IS_OK=0;
else
{
WriteOneByte(0xcc); //跳过序列号
WriteOneByte(0x44); //启动温度转换
Init_DS18B20();
WriteOneByte(0xcc); //跳过序列号
WriteOneByte(0xbe); //读取温度寄存器
Temp_Value[0]=ReadOneByte(); //温度低8位
Temp_Value[1]=ReadOneByte(); //温度高8位
DS18B20_IS_OK=1;
}
}
//-------------------------------------------------------------------------------------------------
//在LCD上显示当前温度
//-------------------------------------------------------------------------------------------------
void Display_Temperature()
{
uchar i;
uchar t=150; //延时值
uchar ng=0; //负数标识
if((Temp_Value[1]&0xf8)==0xf8)
{
Temp_Value[1]=~Temp_Value[1];
Temp_Value[0]=~Temp_Value[0]+1;
if(Temp_Value[0]==0x00) Temp_Value[1]++;
ng=1; //设负数标识
}
//查表得到温度小数部分
Display_Digit[0]=df_Table[Temp_Value[0]&0x0f];
//获取温度整数部分(无符号)
CurrentT=((Temp_Value[0]&0xf0)>>4)|((Temp_Value[1]&0x07)<<4);
//将整数部分分解为三位待显示数字
Display_Digit[3]=CurrentT/100;
Display_Digit[2]=CurrentT%100/10;
Display_Digit[1]=CurrentT%10;
//刷新LCD显示缓冲
Current_Temp_Display_Buffer[11]=Display_Digit[0]+'0';
Current_Temp_Display_Buffer[10]='.';
Current_Temp_Display_Buffer[9]=Display_Digit[1]+'0';
Current_Temp_Display_Buffer[8]=Display_Digit[2]+'0';
Current_Temp_Display_Buffer[7]=Display_Digit[3]+'0';
//高位为0时不显示
if(Display_Digit[3]==0) Current_Temp_Display_Buffer[7]=' ';
//高位为0且次高位为0时,次高位不显示
if(Display_Digit[2]==0&&Display_Digit[3]==0)
Current_Temp_Display_Buffer[8]=' ';
//负数符号显示在恰当位置
if(ng)
{
if(Current_Temp_Display_Buffer[8]==' ')
Current_Temp_Display_Buffer[8]='-';
else
if(Current_Temp_Display_Buffer[7]==' ')
Current_Temp_Display_Buffer[7]='-';
else
Current_Temp_Display_Buffer[6]='-';
}
//在第一行显示标题
Set_LCD_POS(0x00);
for(i=0;i<16;i++)
{
Write_LCD_Data(Temp_Disp_Title[i]);
}
//在第二行显示当前温度
Set_LCD_POS(0x40);
for(i=0;i<16;i++)
{
Write_LCD_Data(Current_Temp_Display_Buffer[i]);
}
//显示温度符号
Set_LCD_POS(0x4d); Write_LCD_Data(0x00);
Set_LCD_POS(0x4f); Write_LCD_Data('C');
}
//-------------------------------------------------------------------------------------------------
//主函数
//-------------------------------------------------------------------------------------------------
void main()
{
Init_LCD();
Read_Temperature();
Delay(50000);
Delay(50000);
while(1)
{
Read_Temperature();
if(DS18B20_IS_OK) Display_Temperature();
DelayXus(100);
}
}