#51 单片机 #DS18B20 #单总线 #温度传感器 #嵌入式时序
前言
DS18B20 是一款常用数字温度传感器,采用One‑Wire 单总线半双工异步串行通信,仅需一根 GPIO 信号线即可完成单片机与传感器的数据交互,广泛用于设备测温、环境测温项目中。难点在于严格的微秒级时序控制,时序出错直接导致读取温度乱码、通信失败CSDN博...。本文梳理硬件参数、单总线原理、全部时序、读取流程、数据解析要点。
一、DS18B20 关键硬件参数
表格
| 参数 | 说明 |
|---|---|
| 测量量程 | -55℃ ~ 125℃ |
| 测量精度 | ±0.5℃,例:真实 25℃,读数区间 24.5‑25.5℃ |
| 分辨率 | 9 位:0.5℃;10 位:0.25℃;11 位:0.125℃;12 位:0.0625℃(最高,常用) |
| 工作电压 | 3V‑5.5V |
分辨率越高,能捕捉越小的温度变化,读数细腻;12 位是工程最常用配置。
二、单总线(One‑Wire)通信基础
-
通信模式 :半双工、异步串行,一根 GPIO 完成收发,总线具备线与特性。
-
线与逻辑
表格
51 单片机输出 DS18B20 输出 总线实际电平 1 0 0 0 1 0 1 1 1 0 0 0 -
引脚模式要点
- 主机发送数据 → GPIO 配置输出模式;
- 主机接收数据 → 释放总线,切换输入模式,不能强行拉高引脚;
- 硬件需要外接 4.7K 上拉电阻,保证总线空闲时为高电平。
- 数据存储:温度原始数据为16 位二进制补码,带符号位扩展,分为低字节、高字节两个字节。
三、完整通信时序(核心!驱动成败关键点)
3.1 复位时序(初始化,每次通信必须先复位)
复位作用:主机和 DS18B20 握手,确认传感器在线可通信。 步骤:
- 主机将总线拉低 480‑960μs,发送复位脉冲;
- 主机释放总线,延时15‑60μs,等待从机应答;
- DS18B20 如果存在,主动把总线拉低 60‑240μs,输出响应脉冲;
- DS18B20 释放总线,总线回到高电平,初始化完成。
如果第 3 步没有拉低应答脉冲:硬件接线错误、缺少上拉电阻、时序延时不对。
3.2 写时序(主机向传感器写 bit)
写 0、写 1 区别在于主机拉低总线持续时间,DS18B20 在 15‑60μs 窗口采样总线电平。
✅ 写 0 时序
- 主机拉低总线,维持60~120μs;
- DS18B20 在 15‑60μs 采样,检测到低电平代表写入 0;
- 主机释放总线。
✅ 写 1 时序
- 主机拉低总线小于 15μs,立刻释放总线;
- DS18B20 采样得到高电平,代表写入 1。
一个字节就是循环 8 次写 bit,低位优先发送。
3.3 读时序(主机读取传感器 bit)
读操作全部由主机发起拉低脉冲,必须在 15μs 以内完成电平采样,超时采样会读到错误电平CSDN博...。
✅ 读 1 时序
- 主机拉低总线 > 1μs,马上释放总线;
- DS18B20 释放总线,总线为高电平;
- 主机15μs 之内采样总线为高电平 → 读到 1。
✅ 读 0 时序
- 主机拉低总线 > 1μs,马上释放总线;
- DS18B20 主动把总线拉低;
- 主机15μs 之内采样总线为低电平 → 读到 0。
读字节:循环调用 8 次读 bit,低位在前。
四、DS18B20 读取温度完整业务流程(单传感器)
单传感器场景使用
0xCC跳过 ROM 命令,不需要匹配设备 ROM 地址;多设备不能使用 0xCC,需要匹配 ROM 命令。
1. ds18b20_reset(); //复位握手
2. write_ds18b20(0xCC); //0xCC=跳过ROM指令,单传感器专用
3. write_ds18b20(0x44); //0x44开启温度转换
4. 延时750ms //等待温度转换完成,必须等待!
5. ds18b20_reset(); //再次复位
6. write_ds18b20(0xCC); //再次跳过ROM
7. write_ds18b20(0xBE); //0xBE读取暂存寄存器温度
8. 读取2字节(低字节、高字节)16位原始温度数据
9. 解析16位补码,换算成实际摄氏度
⚠️坑点:发送 0x44 启动转换之后必须延时等待,没有延时直接读,读出旧温度 / 乱码。
五、16 位补码温度数据解析
12 位分辨率模式:
- Bit15~Bit11:符号位;全 0 代表正温度,全 1 代表负温度;
- Bit10‑Bit4:温度整数部分;
- Bit3‑Bit0:温度小数部分,每一位代表 0.0625℃。
- 正温度:直接将 16 位原始数值 ×0.0625,得到摄氏度;
- 负温度(补码存储):16 位补码取反 + 1 得到绝对值,乘以 0.0625,再添加负号。
示例: 原始数据 0xFC90(补码),符号位为 1,负温度;补码转原码,计算得到 - 55℃。
六、开发踩坑总结
- 时序必须严格微秒级延时,晶振不同,
delay_us延时函数要校准; - 读时序采样窗口只有 15μs,采样动作不能拖到 15μs 之后;
- 启动转换 0x44 之后,必须等待转换时间,不能立刻读;
- 单总线必须上拉电阻,否则总线电平异常,无应答;
- 单传感器才可以使用
0xCC跳过 ROM;多个 DS18B20 挂总线禁止使用 0xCC; - 负数一定要做补码转换,否则负温读数完全错乱。
七、核心函数伪代码参考
//复位
bit ds18b20_reset(void);
//写一个字节
void write_ds18b20(unsigned char dat);
//读一个字节
unsigned char read_ds18b20(void);
//获取处理好的温度
float get_ds18b20_temp(void)
{
unsigned char high,low;
int temp_raw;
ds18b20_reset();
write_ds18b20(0xCC);
write_ds18b20(0x44);
delay_ms(750);
ds18b20_reset();
write_ds18b20(0xCC);
write_ds18b20(0xBE);
low = read_ds18b20();
high = read_ds18b20();
temp_raw = (high<<8)|low;
if(temp_raw & 0xF800) //负温度
{
temp_raw = ~temp_raw + 1;
return -(temp_raw * 0.0625);
}
else
{
return temp_raw * 0.0625;
}
}