(二)、温度传感器
1、One-Wire总线
One-Wire总线利用一根线实现双向通信。因此其协议对时序的要求较严格,如应答等时序都有明确的时间要求。基本的时序包括复位及应答时序、写一位时序读一位时序。单总线即只有一根数据线,系统中的数据交换、控制都由这根线完成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许设备在不发送数据时能够释放总线,而让其他设备使用总线。由于它们是主从结构,只有主机呼叫从机时,从机才能应答,因此主机访问One-Wire器件都必须严格遵循单总线命令序列,即初始化、ROM命令、功能命令。
对于蓝桥杯的同学,One-Wire协议官方会提供,不需要大家自己写。DS18B20的通信过程较为简单。图 五为蓝桥杯DS18B20原理图,DQ即用于通信的单总线,需要在函数开始定义该引脚sbit DQ = P1^4;
DS18B20的通信过程:初始化总线---写ROM指令(跳过ROM指令0xcc)---写RAM指令(开始温度转换0x44)---重新初始化---ROM指令(跳过ROM指令0xcc)---写RAM指令(开始温度读取0xbe)---接收数据(先低位再高位)---分析处理数据。(如图 六)
图 五DS18B20原理图
图 六 DS18B20通信过程
2、代码解读(图 七)(数据处理分析)
数据处理: High<<8 高八位数据以二进制的形式左移八位就变成了unsigned int 类型数据,后八位数据全为0,此时用 | Low 运算符来获取后八位数据,则((High<<8)|Low)就是获取到了初步的温度数据,float(对象)就是强制转换括号中数据为float数据类型,但温度高五位是符号位(图 八),当这五个全是0时温度为正值,全为1则为负值。后四位是小数位,此时要*0.0625或者/16.0来获取到适合的温度区间,例如0000 0000 0000 0011表示十进制数据3,最后一位精度为0.0625,3*0.0625即为温度数据。
图 七 DS18B20代码解读
图 八 DS18B20数据存储位
附相关代码(注意蓝桥杯官方会给初始化、写入、读取等底层)
#include <STC15F2K60S2.H>
#include <INTRINS.h>sbit DQ = P1^4;void Delay_OneWire(unsigned int t)
{unsigned char i;while(t--){for(i=0;i<12;i++);}
}//仿真用这个延时
//void Delay_OneWire(unsigned int t)
//{
// while(t--);
//}//
void Write_DS18B20(unsigned char dat)
{unsigned char i;for(i=0;i<8;i++){DQ = 0;DQ = dat&0x01;Delay_OneWire(5);DQ = 1;dat >>= 1;}Delay_OneWire(5);
}//
unsigned char Read_DS18B20(void)
{unsigned char i;unsigned char dat;for(i=0;i<8;i++){DQ = 0;dat >>= 1;DQ = 1;if(DQ){dat |= 0x80;} Delay_OneWire(5);}return dat;
}//
bit init_ds18b20(void)
{bit initflag = 0;DQ = 1;Delay_OneWire(12);DQ = 0;Delay_OneWire(80);DQ = 1;Delay_OneWire(10); initflag = DQ; Delay_OneWire(5);return initflag;
}/*
DS18B20的通信过程:初始化总线写ROM指令(跳过ROM指令0xcc)写RAM指令(开始温度转换0x44)重新初始化ROM指令(跳过ROM指令0xcc)写RAM指令(开始温度读取0xbe)接收数据(先低位再高位)分析处理数据
*/float Temperature_Read(void)
{unsigned char Low,High;init_ds18b20(); //初始化总线Write_DS18B20(0xcc); //跳过ROM指令Write_DS18B20(0x44); //开始温度转换Delay_OneWire(200);init_ds18b20(); //重新初始化Write_DS18B20(0xcc); //跳过ROM指令Write_DS18B20(0xbe); //开始读取温度(低位优先)Low = Read_DS18B20(); //接收数据(先低位再高位)High = Read_DS18B20();return (float)((High<<8)|Low)/16.0; //分析处理数据
}