第2章 温度传感器(DS18B20):单总线协议详解
DS18B20 这玩意儿,我在温室项目里用了不下上百个。说实话,它是我见过最「省引脚」的数字温度传感器——就一根数据线,既能供电又能传数据。嗯,今天咱们就把它彻底聊透。
2.1 单总线协议到底是什么?
单总线(1-Wire),说白了就是 Dallas 公司搞的一套「一根线走天下」的通信协议。你想想看,传统的 I2C 要两根线,SPI 要三四根,而单总线只需要一根数据线加一根地线。
我刚开始接触时也觉得不可思议:一根线怎么同时传时钟和数据?后来才明白,它靠的是严格的时序——主机通过拉低总线的时间长短来发送「0」和「1」。从机则通过拉低总线来响应。
核心要点:单总线是半双工通信,主机控制所有时序。从机只能被动响应。
2.2 DS18B20 工作原理
DS18B20 内部其实有三个主要部分:
- 64位 ROM 编码:每个芯片独一无二,支持多设备挂在一根总线上
- 温度传感器:核心部件,把温度转换成数字量
- 暂存器(Scratchpad):9字节的临时存储区,存放温度值、配置、CRC 等
我记得第一次用的时候,死活读不到温度。查了半天才发现是 ROM 匹配指令没发对。这里提醒一下:如果你总线上只挂一个 DS18B20,可以用「跳过 ROM」指令(0xCC),省去匹配步骤。
2.3 寄生供电模式
这个模式很有意思。正常供电需要 VDD 接 3.3V 或 5V,但寄生供电模式下,VDD 引脚直接接地,芯片从数据线上「偷电」。
怎么偷的?当总线为高电平时,芯片内部电容充电;当总线为低电平时,电容放电维持工作。但有个坑——温度转换时电流需求大(约 1.5mA),如果总线拉低太久,电容会掉电。
避坑指南:我曾经在温室项目里用了寄生供电,结果冬天温度转换总失败。后来发现是总线拉低时间太长,电容撑不住。解决方案:在数据线上加一个 4.7kΩ 上拉电阻到 VCC,同时确保转换期间总线保持高电平。
我个人习惯:除非引脚特别紧张,否则还是用正常供电模式。寄生供电省的那根线,往往换来一堆调试时间。
2.4 分辨率配置
DS18B20 支持 9 到 12 位分辨率,默认是 12 位。分辨率越高,转换时间越长:
| 分辨率 | 转换时间(典型值) | 温度精度 |
|---|---|---|
| 9 位 | 93.75 ms | 0.5°C |
| 10 位 | 187.5 ms | 0.25°C |
| 11 位 | 375 ms | 0.125°C |
| 12 位 | 750 ms | 0.0625°C |
你想想看,温室环境温度变化很慢,0.5°C 的精度完全够用。我一般设成 9 位,转换一次不到 100ms,省电又快速。
配置分辨率的方法:向暂存器的第 4 字节写入配置值。比如 12 位写 0x7F,9 位写 0x1F。
// 设置 DS18B20 为 9 位分辨率
void setResolution_9bit() {
reset_pulse(); // 复位脉冲
send_byte(0xCC); // 跳过 ROM
send_byte(0x4E); // 写暂存器指令
send_byte(0x00); // TH 用户字节1
send_byte(0x00); // TL 用户字节2
send_byte(0x1F); // 配置寄存器:9位
}
2.5 CRC 校验
单总线通信容易受干扰,尤其是温室里电机启停时。DS18B20 内置了 8 位 CRC 校验,确保数据完整性。
CRC 校验覆盖 8 字节数据(温度 + TH + TL + 配置 + 保留字节),最后一个字节就是 CRC 值。主机收到数据后,用多项式 x⁸ + x⁵ + x⁴ + 1 计算校验。
小技巧:我一般直接用 Dallas 官方提供的 CRC 查表法,速度比计算快得多。代码就几行,网上随便搜都有。
// CRC 校验示例(查表法)
uint8_t crc8(uint8_t *data, uint8_t len) {
uint8_t crc = 0;
uint8_t lookup[] = {
0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83,
// ... 省略中间 248 个值
};
for (uint8_t i = 0; i < len; i++) {
crc = lookup[crc ^ data[i]];
}
return crc;
}
如果计算出的 CRC 和收到的 CRC 不匹配,直接丢弃这帧数据。别犹豫,温室里数据错一位,温度可能差好几度。
2.6 典型电路设计
一个标准的 DS18B20 电路其实很简单:
- 数据线:接 MCU 的 GPIO,加上拉电阻 4.7kΩ 到 VCC
- VDD:接 3.3V 或 5V(正常供电模式)
- GND:共地
但实际项目中,我踩过不少坑:
注意:如果数据线超过 10 米,上拉电阻要减小到 2.2kΩ 甚至 1kΩ。我有个项目线长 30 米,用 4.7kΩ 死活通信不上,换成 1kΩ 就好了。
另外,建议在数据线上加一个 100nF 的电容到地,滤除高频干扰。温室里的变频器、水泵都是干扰源。
// 典型电路连接(正常供电模式)
// MCU GPIO ----[4.7kΩ]---- VCC (3.3V)
// |
// +---- DS18B20 DQ
// DS18B20 VDD ---- VCC (3.3V)
// DS18B20 GND ---- GND
如果你非要用寄生供电,电路改成这样:
// 寄生供电模式
// MCU GPIO ----[4.7kΩ]---- VCC (3.3V)
// |
// +---- DS18B20 DQ
// DS18B20 VDD ---- GND
// DS18B20 GND ---- GND
嗯,寄生供电模式下,转换期间必须保证总线为高电平。我一般用 MOS 管强拉高,或者干脆在转换前把 GPIO 设成输出高。
小结
DS18B20 是个好芯片,便宜、稳定、易用。但单总线的时序要求很严格,稍微偏差一点就通信失败。我的建议是:
- 先用逻辑分析仪抓波形,确认时序正确
- 量产时用正常供电模式,别省那根线
- CRC 校验一定要做,温室环境干扰多
下一章咱们聊聊湿度传感器 SHT30 的 I2C 接口,那个又是另一番天地了。