前言
DS18B20 是一款常用的单总线数字温度传感器,它没有映射到 51 单片机的片内寄存器,所有控制与数据读取都是通过单总线向传感器发送命令,读取传感器内部暂存寄存器完成。单总线为半双工异步串行通信,仅需一根 GPIO 引脚即可完成 51 单片机与 DS18B20 的数据交互。
传感器参数回顾:
- 测量量程:
-55℃ ~ 125℃ - 测量精度:
±0.5℃ - 分辨率可选:9/10/11/12bit,最高分辨率 0.0625℃
- 工作电压:3V‑5.5V
一、DS18B20 核心命令
DS18B20 分为ROM 命令 和功能存储器命令,51 单片机通过模拟单总线时序发送这些命令控制传感器。
1. ROM 命令
| 命令码 | 命令名称 | 作用说明 |
|---|---|---|
| 0xCC | Skip ROM(跳过 ROM) | 系统只有 1 片 DS18B20 时使用,跳过 ROM 地址匹配,直接执行后续功能命令;多传感器系统禁止使用该命令 |
本文为单传感器场景,所以全程使用
0xCC跳过 ROM 命令。
2. 存储器功能命令
| 命令码 | 命令名称 | 作用说明 |
|---|---|---|
| 0x44 | Convert T 温度转换 | 启动 DS18B20 进行温度 AD 转换,最大转换时间 750ms,转换结果保存至传感器内部温度寄存器 |
| 0xBE | Read Scratchpad 读暂存器 | 读取 DS18B20 内部暂存寄存器,读出的第 1 字节为温度低字节 LSB,第 2 字节为温度高字节 MSB |
3.51单片机与ds18b20通信(半双工、异步、串行)

GPIO One-Wire 单总线,传感器通过一根GPIO信号线与单片机通信



二、DS18B20 内部温度寄存器解析
该寄存器位于 DS18B20 传感器内部,不是 51 单片机寄存器,通过
0xBE命令读出,一共 2 字节,组成 16 位二进制补码带符号温度数据。
寄存器位分配(12 位分辨率)
- 低字节 LSB:bit0~bit3 为温度小数部分;bit4~bit7 为温度整数的低 4 位
- 高字节 MSB:bit0~bit3 为温度整数的高 4 位;bit4~bit7 为符号扩展位
分辨率与分度值对照表
| 配置分辨率 | 温度最小分度 |
|---|---|
| 9 bit | 0.5℃ |
| 10 bit | 0.25℃ |
| 11 bit | 0.125℃ |
| 12 bit | 0.0625℃ |
温度数值换算规则
- 正温度 :将拼接完成的 16 位原始数值直接 ×
0.0625,得到实际摄氏度。 - 负温度 :原始数据是二进制补码,需要对 16 位数做
取反+1运算得到绝对值,再 ×0.0625。
三、完整工作操作流程(单传感器)
DS18B20 操作有严格时序顺序,顺序出错会读取乱码。
1. ds18b20_reset(); //单总线复位,初始化传感器
2. write_ds18b20(0xCC); //发送跳过ROM命令
3. write_ds18b20(0x44); //启动温度转换
4. 延时750ms; //等待AD转换完成
5. ds18b20_reset(); //再次复位
6. write_ds18b20(0xCC); //再次跳过ROM
7. write_ds18b20(0xBE); //发送读暂存器命令
8. 读取2字节:LSB、MSB //获取16位温度补码数据
9. 数据解析换算,得到真实温度

四、单总线底层时序要点(51 GPIO 模拟)
DS18B20 单总线包含:复位时序、写时序、读时序 ,时序时间必须严格遵守,时间不对会通信失败。 单总线具备线与特性;读取数据时主机必须释放总线。
4.1 复位时序(存在脉冲检测)
① 主机将总线拉低 480μs ~ 960μs,输出复位脉冲
② 主机释放总线,延时 15μs ~ 60μs
③ DS18B20拉低总线 60μs ~ 240μs,回复响应脉冲(存在脉冲)
④ DS18B20释放总线,总线回到高电平,初始化完成
如果没有检测到响应脉冲,代表传感器未连接或者硬件故障。
4.2 写时序(写 0 / 写 1,write_ds18b20函数底层)
写时序每一位时隙最小 60μs,两次写位之间间隔至少 1μs。
写 0 时序
① 主机拉低总线,维持 60μs ~ 120μs
② DS18B20 在 15‑60μs 时间段采样总线,采样为低电平即识别为0
③ 主机释放总线,完成该bit发送
写 1 时序
① 主机拉低总线,时间小于15μs,随后立刻释放总线
② DS18B20 在15‑60μs时间段采样总线,采样为高电平即识别为1
③ 总线保持高电平,完成该bit发送
4.3 读时序(读 0 / 读 1,读字节函数底层)
⚠️关键点:主机必须在拉低总线后的 15μs 以内完成电平采样,超过 15μs 电平会失效。
读 1 时序
① 主机拉低总线 >1μs,然后释放总线
② DS18B20释放总线,总线为高电平
③ 主机在15μs之内采样总线,读到高电平,代表读取bit=1
读 0 时序
① 主机拉低总线 >1μs,然后释放总线
② DS18B20主动把总线拉低,输出0信号
③ 主机在15μs之内采样总线,读到低电平,代表读取bit=0
注意:每读 1bit 都要重复上面的读时隙操作;读字节时,循环 8 次读时序,拼接成 1 字节数据。
五、简单示例伪代码(数据解析片段)
5.1 温度数据解析片段
unsigned char LSB,MSB;
int temp_raw;
float temp;
//已经读出LSB、MSB
temp_raw = (MSB << 8) | LSB; //拼接16位原始补码
if(temp_raw & 0x8000)
{
//负数处理,补码转真值
temp_raw = ~temp_raw + 1;
temp = -(temp_raw * 0.0625f);
}
else
{
temp = temp_raw * 0.0625f;
}
5.2 写函数伪逻辑
void write_ds18b20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++) //低位先发送
{
if(dat & 0x01)
{
//写1时序
拉低IO;
延时<15us;
释放IO;
}
else
{
//写0时序
拉低IO;
延时60~120us;
释放IO;
}
dat >>= 1;
延时1us;
}
}
小结
- DS18B20 的温度寄存器在传感器内部,51 单片机通过单总线命令读写,不属于单片机片上寄存器。
0x44负责启动转换,必须等待转换时间;0xBE读取 2 字节温度补码。- 温度为 16 位二进制补码,根据符号位区分正负,乘以分度值 0.0625 得到实际温度。
- 时序是驱动成功的关键,复位、写、读时序时间参数不能随意修改,否则数据出错。