一、前言
关于温度传感器这个部分,近几年蓝桥的比赛都出现


所以温度传感器是比较重要的考点,当然学会温度传感器的使用,在其他单片机的开发和应用中,我们也可以融会贯通。
二、DS18B20芯片手册
1、单总线(1-WIRE)
DS18B20使用严格的单总线通信协议来确保数据的完整性,这主要的几种信号类型:复位脉冲,存在脉冲,写入0,写入1,读取0,读取1。注意:除了存在脉冲,其他信号都是通过主控制器启动信号。
(1)初始化过程-复位和存在脉冲
复位和存在脉冲与DS18B20的所有通信都始于由复位脉冲组成的初始化序列从主机接收到DS18B20发出的存在脉冲。
在初始化序列期间,总线主机通过拉动单总线传输(TX)复位脉冲低电压至少480µs。然后总线主机释放总线并进入接收模式(RX)。当总线被释放时,5kΩ上拉电阻将1线总线拉高。当DS18B20检测到对于上升沿,它等待15µs到60µs,然后通过将单总线拉低来传输存在脉冲60µs至240µs。
(2)“读”和“写”的不同
总线主机在写入时隙期间将数据写入DS18B20,并从DS18B20读取数据在读取时隙期间。每个时隙在单总线上传输一位数据
写入时隙
有两种写时隙:“写1”时隙和“写0”时隙。总线主机使用写1时隙向DS18B20写入逻辑1,使用写0时隙向DS18B20写入逻辑0。
DS18B20芯片所有写时隙的持续时间必须至少为60µs,恢复时间必须至少为1µs。
为了生成写1时隙,在将单总线拉低后,总线主机必须释放1线总线在15µs内。当母线被释放时,5kΩ上拉电阻将把母线拉高。生成写0时隙,在单总线拉低后,总线主机必须继续保持总线低电平
时隙持续时间(至少60µs)。
DS18B20在主控后15µs到60µs的窗口期间对单总线进行采样初始化写时隙。如果在采样窗口期间总线高,则向DS18B20写入1。如果线路低,则向DS18B20写入0。
读取时隙
DS18B20只有在主机发出读时隙时才能向主机传输数据。
因此,必须在发出read Scratchpad [BEh]或read Power后立即生成读时隙供应[B4h]命令,以便DS18B20可以提供所请求的数据。另外,可以发出Convert T [44h]或Recall E2 [B8h]命令查询状态后生成读时隙在DS18B20功能命令一节中解释的操作。
所有读时隙的持续时间必须至少为60µs,恢复时间必须至少为1µs槽之间。一个读时隙是由主设备将单总线拉低A发起的最小1µs,然后释放总线。

当主机启动读时隙后,DS18B20将开始在总线上传输1或0。DS18B20通过使总线保持高电平来传输1并通过拉低总线传输一个0。当发送0时,DS18B20将释放总线时隙结束时,母线将被上拉电阻拉回其高空闲状态。输出来自DS18B20的数据在开始读取时隙的下降沿后15µs有效。
因此,主机必须释放总线,然后在从插槽开始的15µs内采样总线状态。对于一个读时隙,TINIT、TRC和TSAMPLE的总和必须小于15µs。

2、原理图
DQ引脚:数据引脚,通过此引脚与传感器进行通信。DS18B20采用了一线制数字接口,通过这一引脚同时传输数据和提供电源,简化了连接。
DS18B20内部有一个低温度系数晶振和一个高温度系数晶振。低温度系数晶振的振荡频率受温度影响很小,用于产生一个固定频率的脉冲信号,这个信号被送往计数器1。而高温度系数晶振的振荡频率会随温度变化而明显改变,其产生的信号作为计数器2的脉冲输入。计数器1和温度寄存器被预置在-55℃所对应的一个基数值。计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1,然后计数器1的预置值重新被装入,并重新开始计数。这个过程一直持续到计数器2计数到0时停止,此时温度寄存器中的数值即为所测温度。
三、DS18B20配置
1、DS18B20复位(操作开始)
2、写入字节0xCC(跳过ROM指令)
3、写入字节0x44(开始温度转换)
4、延时700ms~900ms(给与足够的时间进行温度转换)
5、DS18B20复位
6、写入字节0xCC(跳过ROM指令)
7、写入字节0xBE(读取高速暂存器)
8、读取暂存器的第0字节,即温度数据的LSB(温度数据低八位)
9、读取暂存器的第1字节,即温度数据的MSB(温度数据高八位)
10、DS18B20复位,表示读取数据结束
11、将LSB和MSB整合成一个16位数据
12、判断读取结果的符号,进行正负温度的数据处理
DS18B20以16位带符号扩展的二进制补码形式读出
补充:
正数的补码就是这个正数本身(+1111 0000的补码就是1111 0000)
负数补码需要取反加一(-1000 0000的补码就是0111 1111 + 1 = 1000 0000)
在16数据中,低4位为小数部分,中间7位为整数部分,高5位为符号位
高五位全部是1,表示负数(负温度)
高五位全部是0,表示正数(正温度)
当读出的数据为正温度时,LSB和MSB整合的16位整数直接乘以分辨率。
(LSB+MSB)* 分辨率
当读出的数据为负温度时,LSB和MSB整合的16位整数取反+1后,再乘以分辨率。
(~(LSB+MSB + 1))* 分辨率
unsigned int Read_DS18B20_Temp()
{
unsigned char LSB,MSB; //定义温度高八位和低八位参数
unsigned int Temp; //温度int型参数
init_ds18b20(); //DS18B20复位
Write_DS18B20(0xcc); //跳过ROM指令
Write_DS18B20(0x44); //开始温度转换
init_ds18b20(); //DS18B20复位
Write_DS18B20(0xcc); //跳过ROM指令
Write_DS18B20(0xbe); //读取高速暂存器
LSB = Read_DS18B20(); //读取暂存器,记录LSB
MSB = Read_DS18B20(); //读取暂存器,记录MSB
Temp = (MSB << 8) | LSB; //进行温度整合
//判断获取的Temp是正温度还是负温度
if((Temp & 0xf800) == 0x0000) //(Temp & 0xf800) == 0x0000表示正数
{
Temp = (Temp + (LSB & 0x0f)) * 0.625;
}
return Temp;
}
在温度整合这里,我们使用Temp = (MSB << 8) | LSB;
高八位MSB先右移8位,空出8个位置,在或上低八位LSB,合并成16位数据。
例如:MSB = 0x08,LSB = 0x18
MSB右移8位 = 0x0800
| 低八位LSB = 0x0818,因为任何数 | 0 = 任何数
对于温度数据是int类型及小数和整数部分组成的,运算的时候会出现很多浮点数,在数码管上面很难显示出来。
所以我们先把温度数据右移4位,把小数移出。
Temp = Temp >> 4;
在整数部分先乘10。
Temp = Temp * 10;
最后在进行整数+小数整合。
Temp = Temp + (LSB & 0x0f) * 0.625;
(LSB & 0x0f)为提取LSB低四位,小数部分 0.625为分辨率。