一根数据线挂载数十片数字温度传感器:64位唯一序列号寻址、12位0.0625°C分辨率、±0.5°C精度,含1-Wire时序与STM32驱动实现
多点测温场景中,DS18B20只需一根数据线加地线即可挂载数十片传感器:每片携带64位唯一序列号(家族码28h),12位分辨率下分辨0.0625°C、精度±0.5°C(-10~+85°C)、转换时间750ms。与NTC、Pt100等模拟方案相比,它省去逐点ADC通道与标定,布线成本大幅下降,特别适合机房、冷链、粮仓、养殖与设备多点温度监测,是物联网温控终端与RTU远程终端的常用测温器件。本文基于DS18B20数据手册,详解1-Wire总线时序、寄生供电、多点搜索与STM32驱动实现。
传统模拟测温每增加一个测点就要增加一路信号线与一路ADC通道:NTC分压信号易受线阻与干扰影响,Pt100需要恒流源或桥路调理,测点越多布线与物料成本越高。DS18B20把温度直接转换为数字量,总线控制器与从机之间只靠一条DQ线通信(加地线),所有器件经64位ROM序列号区分,从根上改变多点测温的组网方式。
| 对比项 | DS18B20(数字) | NTC热敏电阻(模拟) | Pt100铂电阻(模拟) |
|---|---|---|---|
| 输出信号 | 数字(1-Wire串行) | 电阻→分压电压 | 电阻→桥路/恒流源电压 |
| 温度分辨率 | 0.0625°C(12位) | 取决于ADC位数 | 取决于ADC位数与调理 |
| 典型精度 | ±0.5°C(-10~+85°C) | 1%~5%(B值误差,需标定) | 较高(A级±0.15°C@0°C) |
| 测点接线 | 1根数据线+地(可寄生供电) | 2线分压 | 2/3/4线 |
| 多点组网 | 一根总线挂多片,64位ROM寻址 | 每点一路ADC | 每点一路调理电路 |
| 转换时间 | 750ms(12位) | 即时(模拟) | 即时(模拟) |
| 软件驱动 | 需实现1-Wire时序 | ADC读取(简单) | 放大/恒流+ADC |
| 单点成本 | 中等 | 低 | 高 |
适用边界同样明确:要求毫秒级响应或超大量测点的场合仍选模拟方案;对成本敏感、响应要求不高(秒级轮询)的多点场景,DS18B20的布线优势非常突出。
DS18B20测温范围-55~+125°C,默认12位分辨率,也可通过暂存器配置寄存器把分辨率降为9~11位以缩短转换时间。转换完成后结果存放在暂存器字节0、1的两字节温度寄存器中,低字节在前。
| 分辨率 | LSB温度步进 | 转换时间(典型) | 适用场景 |
|---|---|---|---|
| 9位 | 0.5°C | 93.75ms | 快速巡检、趋势监测 |
| 10位 | 0.25°C | 187.5ms | 一般环境监测 |
| 11位 | 0.125°C | 375ms | 精度与速度折中 |
| 12位(默认) | 0.0625°C | 750ms | 冷链、高精度监测 |
12位数据为16位符号扩展补码:正温度高位全0,负温度高位全1(-25°C对应0xFFCE)。12位换算公式为T = raw × 0.0625;当温度是整数摄氏度时,raw右移4位(raw>>4)即为带符号整数值。
1-Wire总线空闲为高电平,靠约5kΩ上拉电阻维持,所有从机输出均为漏极开路。任何一次通信都以初始化序列开始:主机拉低总线至少480µs(复位脉冲)后释放,DS18B20检测到上升沿后等待15~60µs,再拉低60~240µs发出存在脉冲;若总线低电平持续超过480µs,总线上所有器件都会被复位。位传输采用时隙方式:写1时隙为拉低1~15µs后释放,写0时隙为拉低60µs,读时隙为拉低约6µs后释放并在15µs内采样。
主机 ──复位脉冲(≥480us)──┐ ┌── 存在脉冲(60~240us)
└──释放───15~60us──┘
DS18B20 ──────────────────┘
写时隙: 写1 = 拉低1~15us后释放(保持60us) 写0 = 拉低60us
读时隙: 主机拉低约6us后释放, 15us内采样电平
命令序列: 初始化 → ROM命令 → 功能命令 → 数据
| 类别 | 命令 | 代码 | 说明 |
|---|---|---|---|
| 温度/数据 | Convert T 温度转换 | 44h | 启动转换,寄生供电时须立即强上拉 |
| Read Scratchpad 读暂存器 | BEh | 读9字节(含第9字节CRC) | |
| 报警/配置 | Write Scratchpad 写暂存器 | 4Eh | 写TH、TL与配置寄存器 |
| Copy Scratchpad 拷贝暂存器 | 48h | 暂存器→EEPROM,需≥10ms强上拉 | |
| 电源/召回 | Recall E2 召回 | B8h | EEPROM→暂存器 |
| Read Power Supply 读供电 | B4h | 读时隙采样:0=寄生供电,1=外部供电 | |
| ROM操作 | Read ROM 读ROM | 33h | 仅总线单器件时使用 |
| Match ROM 匹配ROM | 55h | 后跟64位ROM码定位指定器件 | |
| Skip ROM 跳过ROM | CCh | 单点或广播(多点时仅限读/转换) | |
| Search ROM 搜索ROM | F0h | 用排除法枚举总线上所有器件ROM码 | |
| Alarm Search 报警搜索 | ECh | 仅温度超TH/TL的器件响应 |
暂存器共9字节:字节0、1为温度,2、3为TH/TL,4为配置,5、6保留,7、8为计数寄存器(可用于提高分辨率),第9字节为前8字节的CRC,多项式为X8+X5+X4+1。读暂存器时主机应校验CRC,不匹配即丢弃本次数据,可有效拦截总线干扰。
DS18B20可在数据线高电平期间把能量储存在内部电容中,低电平期间靠电容供电工作,这就是寄生供电模式:远距离测温无需本地电源,甚至可以在没有常规电源时读ROM。但转换或拷贝EEPROM时器件工作电流可达1.5mA,仅靠5kΩ上拉电阻供电不足,主机必须在发出44h或48h命令后10µs内把DQ切换到强上拉(用MOSFET把总线直接接到电源轨),并在整个转换期间保持,12位转换需保持750ms、拷贝EEPROM需10ms。
3.3V/5V
│
[MOSFET]←─PB0(强上拉使能)
│
MCU DQ─PB5─┴──────┬──────┬────── DQ
[4.7kΩ上拉] │ │
┌─────┴──┐ ┌─┴──────┐
│DS18B20 │ │DS18B20 │ ...
│DQ VDD G│ │DQ VDD G│
└───┬────┘ └───┬────┘
GND ────────────┴──────────┴──────────
寄生供电: VDD接GND; 外部供电: VDD接电源, 无需强上拉
工程要点:温度高于100°C时不推荐寄生供电(高温漏电流增大,通信可能失败),应改用VDD外部供电;多点同时转换时,外部供电方式可先发Skip ROM再发44h让所有器件并行转换,节省总轮询时间。主机可用B4h命令查询供电模式以决定是否启用强上拉。
系统首次上电时主机不知道总线上挂了多少片、ROM码是什么,需要用Search ROM(F0h)逐位扫描:对ROM的每一位,主机先发两个读时隙,从机依次送出该位的正相与反相电平,据此判断该位状态——"01"表示该位为0、"10"表示该位为1、"00"表示多位冲突(需按已记录的路径选择分支)、“11”表示总线上无器件。逐位回溯分支即可枚举全部ROM码。
1-Wire时序用GPIO位操作即可实现,关键是把DQ引脚配置为开漏输出(配合外部4.7kΩ上拉),读写时隙误差控制在±几微秒内。以下是基于HAL库的完整驱动骨架。
/* 引脚: PB5=DQ, 开漏; PB0=强上拉MOSFET控制 */
#define OW_PORT GPIOB
#define OW_PIN GPIO_PIN_5
#define STRONG_PORT GPIOB
#define STRONG_PIN GPIO_PIN_0
static void ow_pin_out(void) { /* GPIOB PIN5 -> GPIO_MODE_OUTPUT_OD 开漏 */ }
static void ow_pin_in(void) { /* GPIOB PIN5 -> GPIO_MODE_INPUT 上拉 */ }
/* 复位: 返回1表示检测到存在脉冲 */
uint8_t onewire_reset(void) {
uint8_t present = 0;
ow_pin_out();
HAL_GPIO_WritePin(OW_PORT, OW_PIN, GPIO_PIN_RESET); /* 拉低 */
delay_us(480); /* >=480us */
ow_pin_in(); /* 释放 */
delay_us(70); /* 等15~60us后采样 */
present = (HAL_GPIO_ReadPin(OW_PORT, OW_PIN) == GPIO_PIN_RESET);
delay_us(410); /* 收尾 */
return present;
}
static void onewire_write_bit(uint8_t bit) {
ow_pin_out();
HAL_GPIO_WritePin(OW_PORT, OW_PIN, GPIO_PIN_RESET);
if (bit) { delay_us(8); HAL_GPIO_WritePin(OW_PORT, OW_PIN, GPIO_PIN_SET); delay_us(55); }
else { delay_us(60); HAL_GPIO_WritePin(OW_PORT, OW_PIN, GPIO_PIN_SET); delay_us(5); }
}
static uint8_t onewire_read_bit(void) {
uint8_t v;
ow_pin_out();
HAL_GPIO_WritePin(OW_PORT, OW_PIN, GPIO_PIN_RESET);
delay_us(6);
ow_pin_in(); /* 释放 */
delay_us(9);
v = HAL_GPIO_ReadPin(OW_PORT, OW_PIN); /* 15us内采样 */
delay_us(50);
return v;
}
void onewire_write_byte(uint8_t b) {
for (uint8_t i = 0; i < 8; i++) onewire_write_bit(b & (1 << i));
}
uint8_t onewire_read_byte(void) {
uint8_t b = 0;
for (uint8_t i = 0; i < 8; i++) if (onewire_read_bit()) b |= (1 << i);
return b;
}
/* 单点读温度(12位): 返回原始值, 温度 = raw * 0.0625 */
int16_t ds18b20_read_raw(void) {
uint8_t sp[9];
if (!onewire_reset()) return 0x8000; /* 总线无器件 */
onewire_write_byte(0xCC); /* Skip ROM */
onewire_write_byte(0x44); /* Convert T */
HAL_GPIO_WritePin(STRONG_PORT, STRONG_PIN, GPIO_PIN_SET); /* 强上拉 */
while (!onewire_read_bit()); /* 转换完成=1 */
HAL_GPIO_WritePin(STRONG_PORT, STRONG_PIN, GPIO_PIN_RESET);
onewire_reset();
onewire_write_byte(0xCC);
onewire_write_byte(0xBE); /* Read Scratchpad */
for (uint8_t i = 0; i < 9; i++) sp[i] = onewire_read_byte();
if (crc8_ds18b20(sp, 8) != sp[8]) return 0x7FFF; /* CRC失败 */
return (int16_t)((sp[1] << 8) | sp[0]);
}
/* 12位换算: float temp = raw * 0.0625f; 整数度: (int8_t)(raw >> 4) */
多片组网时把读温度函数改为:复位 → 55h + 64位ROM码 → BEh 读取,即可按ROM码逐片读取;MCU主频越高越要注意delay_us在关中断下的准确性,建议用定时器微秒延时替代软件空循环。
总结:DS18B20以一根数据线承载多点测温,12位0.0625°C分辨率与±0.5°C精度满足绝大多数环境监测需求,64位ROM寻址配合Search ROM算法即可自动发现并轮询总线上全部器件。驱动实现的关键在于精确的位时序、强上拉管理(寄生供电时10µs内切换)与CRC校验,三者到位即可稳定组网,适合物联网温控终端与RTU远程终端的低布线成本多点测温设计。
本文基于《DS18B20中文资料》与DS18B20数据手册等资料整理优化。
沧州艾诺威电子 — 国家高新技术企业,20+项国家专利
嵌入式系统开发 · 物联网方案 · AI智能硬件 · 一站式交付
电话:13930711029 | 邮箱:tech@czinv.com | 24小时内响应