主要是对主函数逻辑的编写,主要有两个注意点:
①将按键换成定时器扫描,要注意,单总线进行传输时,要关闭定时器中断,传输结束后再打开定时器,所有的单总线都得这样。因为单总线中必须要进行延时操作。如果在延时操作时,中断触发,去执行中断函数中的内容,则单总线的时序就发生了变化,影响到单总线的运行。这就是单总线比较鸡肋的地方。IIC则不会,因为IIC是时钟控制,时钟变化,数据才进行传输。
②显示精度的问题:显示小数部分,先化为整数,强制类型转化为长整型(因为整型的范围是65535,小数点乘以10000,用整型可能范围不够用),再取余,这里可以通过控制T*?来控制显示的精度
main.c
#include <REGX52.H>
#include "LCD1602.h"
#include "DS18B20.h"
#include "Delay.h"
#include "key.h"
#include "Timer0.h"
#include "AT24C02.h"
float T,TShow;
char TLow,THigh;
unsigned char KeyNum;
void main()
{
DS18B20_ConvertT();//上电先转换一次温度,防止第一次读数据错误
Delay(1000); //等待转换完成
THigh=AT24C02_ReadByte(0);//读取温度阈值数据
TLow=AT24C02_ReadByte(1);
if(THigh>125 || TLow<-55 || THigh<=TLow)
{
THigh=20; //如果阈值非法,则设为默认值
TLow=15;
}
LCD_Init();
LCD_ShowString(1,1,"T:");
LCD_ShowString(2,1,"TH:");
LCD_ShowString(2,9,"TL:");
LCD_ShowSignedNum(2,4,THigh,3);
LCD_ShowSignedNum(2,12,TLow,3);
Timer0_Init();
while(1)
{
KeyNum=key();
/*温度读取及显示*/
DS18B20_ConvertT(); //转换温度
T=DS18B20_ReadT(); //读取温度
if(T<0) //如果温度小于0
{
LCD_ShowChar(1,3,'-');//显示负号
TShow=-T; //将温度变为正数
}
else //如果温度大于等于0
{
LCD_ShowChar(1,3,'+');//显示正号
TShow=T;
}
LCD_ShowNum(1,4,TShow,3);//显示温度整数部分
LCD_ShowChar(1,7,'.');
LCD_ShowNum(1,8,(unsigned long)(TShow*100)%100,2);
//显示小数部分,先化为整数
//强制类型转化为长整型,再取余
//这里可以通过控制T*?来控制现实的精度
/*阈值判断及显示*/
if(KeyNum)//有按键按下再进去,要不然一直扫描比较耗费时间
{
if(KeyNum==1)
{
THigh++;
if(THigh>125){THigh=125;}
}
if(KeyNum==2)
{
THigh--;
if(THigh<=TLow){THigh++;}
}
if(KeyNum==3)
{
TLow++;
if(TLow>=THigh){TLow--;}
}
if(KeyNum==4)
{
TLow--;
if(TLow<-55){TLow=-55;}
}
LCD_ShowSignedNum(2,4,THigh,3);
LCD_ShowSignedNum(2,12,TLow,3);
AT24C02_WriteByte(0,THigh);
Delay(5);
AT24C02_WriteByte(1,TLow);
Delay(5);
}
if(T>THigh)
{
LCD_ShowString(1,13,"OV:H");
}
else if(T<TLow)
{
LCD_ShowString(1,13,"OV:L");
}
else
{
LCD_ShowString(1,13," ");
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=20)
{
T0Count=0;
Key_Loop();
}
}