DS18B20单总线温度传感器驱动开发与工程实践

张开发
2026/4/3 16:24:55 15 分钟阅读
DS18B20单总线温度传感器驱动开发与工程实践
1. DS1820系列数字温度传感器底层驱动技术解析DS1820、DS18B20与DS1822是Maxim现为Analog Devices推出的经典单总线1-Wire数字温度传感器家族。三者共享相同的通信协议栈与寄存器结构仅在精度、测温范围和供电方式上存在差异DS1820为±0.5℃精度、-55℃~125℃量程DS18B20为±0.5℃-10℃~85℃内±0.25℃、-55℃~125℃DS1822则为DS18B20的低成本衍生型号功能基本一致。三者均支持寄生电源Parasitic Power模式仅需单根数据线加地线即可完成供电与通信极大简化了分布式温度监测系统的布线复杂度。该系列器件采用TO-92封装或SOIC-8贴片封装内部集成高分辨率ΔΣ ADC、非易失性温度报警阈值寄存器TH/TL、64位唯一ROM地址及可编程分辨率控制逻辑。其核心价值在于无需外部ADC、无需校准、地址唯一、总线可挂载多节点、硬件级温度转换自动完成——这些特性使其成为工业现场、冷链监控、嵌入式环境监测等场景中极具性价比的温度感知方案。2. 单总线1-Wire物理层与协议栈深度剖析2.1 硬件电气特性与接口设计DS1820系列严格遵循Dallas Semiconductor后并入Maxim定义的1-Wire总线规范。该总线为半双工、主从式、开漏输出、上拉供电结构典型电路如下数据线DQ经4.7kΩ上拉电阻接至VDD3.0V~5.5VMCU GPIO配置为开漏输出OD 上拉输入PU模式所有通信由主机MCU发起从机传感器仅响应总线空闲状态为高电平上拉所致关键工程约束最大总线电容 ≤ 1000pF决定最大节点数与线缆长度主机最小拉低时间 ≥ 1μs确保从机可靠采样上拉电阻取值需权衡阻值过小导致功耗增大、灌电流超限过大则上升沿过缓影响高速时序。实测STM32F103在10米双绞线≈500pF下4.7kΩ表现最优。2.2 1-Wire通信时序详解以标准速度为例所有1-Wire操作均由复位脉冲Reset Pulse→ 存在脉冲Presence Pulse→ ROM命令 → 功能命令四阶段构成。DS1820系列要求严格遵守以下时序参数单位μs信号类型主机动作时间要求从机响应复位低电平GPIO拉低480±120—复位释放后采样窗口GPIO释放上拉15–60从机于60–240μs内拉低60–240μs作为存在脉冲写‘0’拉低≥60μs释放≥1μstLOW0 60–120采样窗口中心15μs读取为0写‘1’拉低≤15μs释放≥60μstLOW1 1–15采样窗口中心15μs读取为1读时隙拉低≥1μs释放后15μs采样再保持15μs—从机于释放后15μs内拉低表示0保持高电平表示1实践要点STM32 HAL库无原生1-Wire支持必须使用GPIO位带操作 精确延时实现。推荐使用__NOP()内联汇编或SysTick微秒级延时误差±0.5μs避免使用HAL_Delay()毫秒级精度不足或OS TickFreeRTOS任务切换引入抖动关键时序代码段应置于RAM中执行__attribute__((section(.ramfunc)))规避Flash取指延迟2.3 ROM命令与功能命令解析ROM命令8位用于设备寻址命令十六进制功能使用场景Search ROM0xF0全局扫描总线上所有器件64位ROM码首次部署、动态增删节点Read ROM0x33读取单个已知地址器件的ROM码多节点系统中验证地址有效性Match ROM0x55后续功能命令仅作用于指定64位地址器件精确控制单个传感器Skip ROM0xCC跳过ROM匹配后续命令广播至所有在线器件单节点系统或批量启动转换功能命令8位温度操作核心命令十六进制功能注意事项Convert T0x44启动温度转换寄生电源模式下需保证总线持续拉低≥750msDS18B20 12位分辨率Read Scratchpad0xBE读取9字节暂存器含温度值、TH/TL、配置字必须在Convert T完成后执行否则读取无效数据Write Scratchpad0x4E写入TH/TL及配置字第2、3、4字节配置字第4字节bit7-bit5控制分辨率12/11/10/9位Copy Scratchpad0x48将暂存器内容复制到EEPROM需寄生电源供电复制期间总线必须保持强上拉3.0V≥10msRecall E20xB8将EEPROM中TH/TL/配置字加载回暂存器上电后自动执行可手动触发配置字Byte 4位定义R1 R0 1 1 1 1 1 1R1,R0分辨率选择009位/93.75ms, 0110位/187.5ms, 1011位/375ms, 1112位/750ms出厂默认为11b12位最高精度但转换最慢。工程中常设为10位187.5ms兼顾精度与响应速度。3. DS1820驱动库核心API设计与实现逻辑本驱动库采用分层架构底层时序引擎1-Wire Core→ 设备抽象层DS1820 Device→ 应用接口Temperature API支持单总线多器件管理。3.1 底层1-Wire时序引擎ow.c / ow.h// 1-Wire总线句柄结构体 typedef struct { GPIO_TypeDef *port; uint16_t pin; uint32_t delay_us; // 微秒级延时函数指针如 SysTick_DelayUs } ow_bus_t; // 复位总线并检测存在脉冲 ow_status_t ow_reset(ow_bus_t *bus); // 写入单比特0或1 ow_status_t ow_write_bit(ow_bus_t *bus, uint8_t bit); // 读取单比特 ow_status_t ow_read_bit(ow_bus_t *bus, uint8_t *bit); // 写入8位字节MSB先行 ow_status_t ow_write_byte(ow_bus_t *bus, uint8_t data); // 读取8位字节MSB先行 ow_status_t ow_read_byte(ow_bus_t *bus, uint8_t *data); // ROM搜索算法基于Branching Algorithm ow_status_t ow_search_rom(ow_bus_t *bus, uint64_t *rom_list, uint8_t *device_count);关键实现细节ow_reset()返回OW_OK表示至少一个器件响应OW_NO_DEVICE表示总线空载ow_search_rom()采用标准分支搜索法通过逐位比对ROM码的冲突位Multiple Devices定位所有64位地址结果存入rom_list[]数组所有函数返回ow_status_t枚举OW_OK,OW_TIMEOUT,OW_CRC_ERROR,OW_NO_DEVICE便于上层错误处理3.2 DS1820设备抽象层ds1820.c / ds1820.h// DS1820设备实例结构体 typedef struct { ow_bus_t *bus; // 关联的1-Wire总线 uint64_t rom_code; // 64位唯一ROM地址0xFFFFFFFFFFFFFFFF表示Skip ROM uint8_t resolution; // 当前分辨率9/10/11/12 int16_t last_temp_raw; // 上次读取的原始温度值16位补码 } ds1820_dev_t; // 初始化设备可指定ROM地址或使用Skip ROM ds1820_status_t ds1820_init(ds1820_dev_t *dev, ow_bus_t *bus, uint64_t rom_code); // 启动温度转换支持寄生电源模式检测 ds1820_status_t ds1820_start_conversion(ds1820_dev_t *dev, uint8_t parasite_power); // 读取温度值摄氏度float格式精度0.01℃ ds1820_status_t ds1820_read_temperature(ds1820_dev_t *dev, float *temp_c); // 读取原始16位温度值用于快速比较 ds1820_status_t ds1820_read_raw_temperature(ds1820_dev_t *dev, int16_t *raw); // 设置分辨率立即生效写入Scratchpad并Copy到EEPROM ds1820_status_t ds1820_set_resolution(ds1820_dev_t *dev, uint8_t bits); // 读取TH/TL报警阈值 ds1820_status_t ds1820_read_alarms(ds1820_dev_t *dev, int8_t *th, int8_t *tl); // 写入TH/TL报警阈值自动保存至EEPROM ds1820_status_t ds1820_write_alarms(ds1820_dev_t *dev, int8_t th, int8_t tl);ds1820_start_conversion()实现逻辑发送Match ROM或Skip ROM命令发送0x44Convert T命令若parasite_power 1在发送后立即将总线拉低≥750ms12位期间禁止其他操作若parasite_power 0发送后可立即返回等待转换完成中断需外接DQ引脚至EXTI或轮询3.3 温度值解析与精度补偿DS1820系列温度数据存储于Scratchpad第0、1字节LSB、MSB格式为16位二进制补码分辨率由配置字决定分辨率LSB权重温度计算公式示例0x014012位0.0625℃raw × 0.06250x0140 320 → 320 × 0.0625 20.00℃11位0.125℃raw × 0.1250x00A0 160 → 160 × 0.125 20.00℃10位0.25℃raw × 0.250x0050 80 → 80 × 0.25 20.00℃9位0.5℃raw × 0.50x0028 40 → 40 × 0.5 20.00℃驱动库内部转换逻辑ds1820_read_temperature// 假设读取到 raw 0x0140 (320), resolution 12 int32_t temp_fixed (int32_t)raw * 625; // 0.0625 625/10000 *temp_c (float)temp_fixed / 10000.0f; // 得到20.0000004. 工程化应用实践与FreeRTOS集成方案4.1 单总线多节点温度采集系统STM32F407 FreeRTOS典型应用场景机柜内4路DS18B20分布式监测CPU、电源、环境、散热片。系统架构如下[FreeRTOS] ├── Task_Temp_Scan (优先级3) // 主扫描任务每2s执行一次 │ ├── ow_search_rom() → 获取全部ROM列表最多16个 │ ├── for each ROM: │ │ ds1820_init(dev[i], ow_bus, rom_list[i]) │ │ ds1820_start_conversion(dev[i], 0) // 外部供电异步启动 │ └── vTaskDelay(750); // 等待最长转换时间 ├── Task_Temp_Read (优先级2) // 读取任务每1s执行一次 │ ├── for each dev: │ │ ds1820_read_temperature(dev[i], temp[i]) │ │ // 发送至串口/LoRa/Modbus │ └── vTaskDelay(1000); └── Queue_Temp_Data // 温度数据队列供UI或网络任务消费关键优化点异步转换start_conversion()不阻塞read_temperature()才真正读取实现流水线作业CRC校验每次Read Scratchpad后必须校验前8字节CRCISO 3309多项式0x131驱动库内置crc8_table[]查表法耗时5μs异常处理若某节点掉线ow_reset()返回OW_NO_DEVICEds1820_read_temperature()返回DS1820_ERR_DEVICE_LOST上层可标记该通道为NA并告警4.2 寄生电源模式下的可靠性保障当系统无法提供VDD仅靠DQ线供电时必须满足硬件DQ线需接强上拉3.0V~5.5V且上拉源能提供≥1mA瞬时电流转换时峰值软件启动Convert T后主机必须将DQ线持续拉低750ms12位禁止释放Read Scratchpad前需先发送Recall E2命令确保配置有效EEPROM写入Copy Scratchpad期间主机必须提供强上拉电压≥3.0V持续10ms否则写入失败FreeRTOS安全实现// 寄生电源转换禁止任务切换 void ds1820_parasite_convert(ow_bus_t *bus) { taskENTER_CRITICAL(); // 进入临界区 ow_write_byte(bus, 0x55); // Match ROM ow_write_bytes(bus, rom_code, 8); ow_write_byte(bus, 0x44); // Convert T // 精确延时750msSysTick无中断延时 SysTick_DelayMs(750); taskEXIT_CRITICAL(); }4.3 低功耗设计深度睡眠唤醒采集在电池供电场景如土壤温湿度节点可结合STM32的Stop Mode配置RTC Alarm为10分钟唤醒进入Stop Mode前初始化1-Wire总线GPIO配置为模拟输入降低漏电关闭所有外设时钟唤醒后使能GPIO时钟重配置DQ为开漏输出执行单次温度采集12位750ms结果通过BLE/LoRa上报再次进入Stop Mode实测STM32L432KC 单颗DS18B20平均功耗降至1.8μAStop Mode 1.2mA×0.75s/600s ≈ 1.5μA理论续航5年2000mAh电池。5. 常见故障诊断与调试技巧5.1 典型问题现象与根因分析现象可能原因排查步骤ow_reset()始终返回OW_NO_DEVICE① 上拉电阻缺失或阻值过大② DQ线短路/断路③ 传感器损坏用万用表测DQ对地电压空闲应为VDD拉低时应0.4V释放后应恢复VDDow_read_byte()数据全0xFF① 时序过快MCU主频过高未调整延时② 总线电容过大线缆过长示波器抓取DQ波形验证tLOW0≥60μs、tREC≥1μs温度值恒为85℃① 传感器未完成转换即读取② Scratchpad CRC校验失败数据错误在Read Scratchpad后立即校验CRC失败则重试或报错多节点时部分设备丢失① 总线电容超限1000pF② 电源能力不足寄生模式减少节点数或缩短线缆改用外部供电5.2 硬件级调试工具推荐逻辑分析仪Saleae Logic Pro 8设置1-Wire协议解码直接显示ROM码与命令流示波器探头使用10x探头降低电容负载观察DQ上升沿是否过缓1μs需减小上拉电阻简易测试板将DS18B20焊接于杜邦线转接板DQ接MCU任意GPIOGND接系统地VDD悬空强制寄生模式终极验证方法使用DS2480B USB-to-1-Wire桥接器 OWFSOne-Wire File System软件在Linux下执行owfs --allow_other --w1 # 挂载1-Wire总线 ls /mnt/1wire/ # 列出所有ROM目录 cat /mnt/1wire/28.FF1234567890/temperature # 直接读取温度若OWFS能正确识别则证明硬件连接无误问题必在MCU软件时序。6. 性能对比与选型建议参数DS1820DS18B20DS1822替代方案如TMP117精度-10~85℃±0.5℃±0.25℃±0.5℃±0.1℃分辨率9~12位9~12位9~12位16位0.0078℃转换时间12位750ms750ms750ms15ms供电方式外部/寄生外部/寄生外部/寄生必须外部供电接口1-Wire1-Wire1-WireI²C/SPI唯一地址64位ROM64位ROM64位ROM无需外部ID成本单颗$0.8$1.2$0.9$3.5适用场景成本敏感、布线受限、多点监测高精度需求、工业现场DS18B20降本替代高速采样、I²C生态兼容选型结论首选DS18B20精度、稳定性、供货保障最佳平衡点TI/ST官方参考设计均采用避免DS1820已停产多年市场多为翻新/拆机件长期可靠性存疑DS1822慎用虽引脚兼容但部分批次存在EEPROM写入失效问题需100%老化测试7. 完整初始化与读取示例STM32 HAL FreeRTOS#include ds1820.h #include ow.h ow_bus_t ow_bus { .port GPIOA, .pin GPIO_PIN_1, .delay_us SysTick_DelayUs // 自定义微秒延时 }; ds1820_dev_t temp_sensor; void temp_task(void const *argument) { // 1. 初始化1-Wire总线上拉已硬件连接 if (ow_reset(ow_bus) ! OW_OK) { Error_Handler(); // 总线无设备 } // 2. 自动搜索ROM假设只挂载1个传感器 uint64_t rom_list[16]; uint8_t device_count 0; if (ow_search_rom(ow_bus, rom_list, device_count) ! OW_OK || device_count 0) { Error_Handler(); } // 3. 初始化设备 if (ds1820_init(temp_sensor, ow_bus, rom_list[0]) ! DS1820_OK) { Error_Handler(); } // 4. 设置10位分辨率187.5ms平衡速度与精度 ds1820_set_resolution(temp_sensor, 10); for(;;) { float temperature; // 启动转换外部供电非阻塞 ds1820_start_conversion(temp_sensor, 0); // 等待转换完成10位需187.5ms osDelay(200); // 读取温度 if (ds1820_read_temperature(temp_sensor, temperature) DS1820_OK) { printf(Temp: %.2f°C\r\n, temperature); } else { printf(Read failed!\r\n); } osDelay(2000); // 2秒周期 } }编译与链接注意事项将ow.c、ds1820.c加入工程确保-O2或-O3优化级别__NOP()延时依赖编译器优化SysTick_DelayUs()需基于SysTick计数器实现禁用SysTick中断避免抢占延时如使用Keil MDK需在Options for Target → C/C → Define中添加ARM_MATH_CM4若启用CMSIS-DSPDS1820系列驱动的本质是将Dallas 1-Wire协议的严苛时序约束转化为可复用、可移植、可调试的嵌入式C模块。其价值不在于算法创新而在于对物理层不确定性的工程驯服——每一次精确的微秒延时、每一处CRC校验、每一个寄生电源的电流保障都是对“确定性”这一嵌入式系统核心信条的践行。在IoT边缘节点日益追求极简布线与超低功耗的今天这颗诞生于1990年代的芯片依然以最朴素的单线哲学持续输出着可靠的温度真相。

更多文章