项目场景:
当我们在学习51单片机的时候,有一部分的题目需要时间和温度数据同时存在,而使用51单片机产生时钟数据的最常用手段为定时器中断和使用DS1302时钟芯片。
问题描述:
定时器中断在实际应用中容易出现温度的读取数据出现乱码,影响了对温度的采集可靠性。 在下图中是DS18B20读取温度数据的部分函数以及部分定时器中断函数。
void Ds18b20WriteByte(u8 dat)
{
u16 i, j;
for(j=0; j<8; j++)
{
DSPORT = 0;
i++;
DSPORT = dat & 0x01;
i=6;
while(i--);
DSPORT = 1;
dat >>= 1;
}
}
u8 Ds18b20ReadByte()
{
u8 byte, bi;
u16 i, j;
for(j=8; j>0; j--)
{
DSPORT = 0;
i++;
DSPORT = 1;
i++;
i++;
bi = DSPORT;
byte = (byte >> 1) | (bi << 7);
i = 4;
while(i--);
}
return byte;
}
void Timer0_Init()
{
TMOD = 0x01;
TH0 = 0xFF;
TL0 = 0x9C;
EA = 1;
ET0 = 1;
TR0 = 1;
}
原因分析:
在图中可以看到在定时器中断里使用的是100us的初始值,在此时温度读取的数据在LCD1602上显示会出现乱码,原因在定时器的中断打断了温度的传输等待时间,使数据传输不完整。
解决方案:
解决的方案是在进行DS18B20温度数据读写的进程前关闭总中断,也就是令EA=0;在温度数据读写进程完成之后在打开总中断,需要注意的是,这种操作会影响定时的精确度,因为这样会有一段定时器中断无法产生时钟数据的空白期。所以如果采用这种方式,建议降低对温度读写函数的调用频率。(本文中采用的DS18B20驱动引自普中科技官方例程,只为分享解决bug的经验)
int Ds18b20ReadTemp()
{
int temp = 0;
uchar tmh, tml;
EA=0;
Ds18b20ChangTemp();
Ds18b20ReadTempCom();
tml = Ds18b20ReadByte();
tmh = Ds18b20ReadByte();
temp <<= 8;
temp |= tml;
EA=1;
return temp;
}