蓝桥杯单片机DS18b20单总线测温模块常见问题解决
有道是:“溪水声声留我住,梅花朵朵唤人回”
DS18b20测温模块作为一个比较简单、稳定的蓝桥杯单片机外设模块,
使用时却经常出现各种问题,总是让我们不禁三番多次回顾其基础知识,
却总也摸不着头脑,
那本文也许就是你的救星,你的百度搜索也将到此截止。
DS18B20是单总线数字化温度传感器,应用非常广泛。
它输出的是数字信号,同时具有体积小,硬件资源耗费少,抗干扰能力强,精度高等特点。
但我们在使用的时候它显得并不“稳定”,总是会出现许多问题,例如:
1.DS18b20温度显示会跳动、跳变
2.DS18b20开机显示85.00之类的
3.DS18b20一直显示35.93度,且温度不刷新
本文将分析以上问题的原理以及提供解决思路。
目录
1.DS18b20温度显示会跳动、跳变
2.DS18b20开机显示85.00之类的
3.DS18b20一直显示35.93度,且温度不刷新
#DS18B20的温度转换与读取流程
1.DS18b20温度显示会跳动、跳变
现象:例如需要显示的温度为:26.1,而数码管显示在26.1和3.5
(或者其他的一些不该出现的值)之间来回跳变。
原因: 没有考虑到单片机进入中断对onewire时序的影响。
造成时序紊乱,读出来的温度值自然是乱的。
解决:在官方给出的驱动必要处加上EA = 0;
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
EA = 0;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
EA = 1;
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
EA = 0;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
EA = 1;
return dat;
}
2.DS18b20开机显示85.00之类的
原因:因为温度传感器的温度转换需要一定的时间,所以刚一开始温度转换然后紧接着读取温度,再显示出来,他读取的温度便是上一次转换的结果,由于ds18b20初始温度值为85,所以这里的“上一次转换的结果”就是85.
解决方法:
在程序初始化的部分加上
Read_Temperature();//此时读取的温度值为默认的85
Delay_1ms(750);//等待上一个read函数温度转换完成
Read_Temperature();
//此时再读取的温度值就变成了第一个read函数转换完成的温度值
先读,再延时较长时间,在进行后续要求的读取
3.DS18b20一直显示35.93度,且温度不刷新
原因:
最基础的原因:用标志刷新读取手法时 标志位 数据类型容量溢出导致计数不到那个值,比如要计数到500的,但定义的count是char类型的,这根本不可能计数到500因为到255就溢出了
时序原因
DS18B20最高具有12为精度(默认模式),分辨率达到0.0625摄氏度,且外围电路极其简单,甚至可以不接VCC,就靠数据流吊着就能工作。当然它工作时时序可没有那么简单,稍有不慎(延时错误),整个工作时序就混乱了,因此准确把握每次延时至关重要。
解决方法:检查时序
比赛方提供的驱动程序中有单总线驱动,官方给配的,十有八九好使,不过我在用的过程中却发现有时都回来数据是错的,温度没读对,在仔细研究后发现,官方给的驱动是针对STC89C52的,其中给的延时函数如下:
而我们实际用的芯片是IAP15系列,作为1T单片机,指令执行速度是12T单片机的12倍,那么上面这个简陋延时函数实际上是以原来的1/12时间就执行完了,这个延时在DS18B20中能够正常使用吗?当然不能,因此在上述函数基础上进行改进:
#DS18B20的温度转换与读取流程
【1】DS18B20复位
【2】写入字节0xcc,跳过ROM指令
【3】写入字节0x44,开始温度转换
【4】延时700~900ms
【5】DS18B20复位
【6】写入字节0xcc,跳过ROM指令
【7】写入字节0xbe,读取高速暂存器
【8】读取暂存器第0字节,即温度数据的LSB
【9】读取暂存器第1字节,即温度数据的MSB
【10】DS18B20复位,表示读取数据结束
【11】将LSB和MSB整合成为一个16位数据
【12】判断读取结果的符号,进行正负温度的数据处