Linux入门DAY42【51 单片机】DS18B20 数字温度传感器完整解析(单总线原理 + 时序 + 读取流程)

#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)通信基础

  1. 通信模式 :半双工、异步串行,一根 GPIO 完成收发,总线具备线与特性。

  2. 线与逻辑

    表格

    51 单片机输出 DS18B20 输出 总线实际电平
    1 0 0
    0 1 0
    1 1 1
    0 0 0
  3. 引脚模式要点

  • 主机发送数据 → GPIO 配置输出模式;
  • 主机接收数据 → 释放总线,切换输入模式,不能强行拉高引脚;
  • 硬件需要外接 4.7K 上拉电阻,保证总线空闲时为高电平。
  1. 数据存储:温度原始数据为16 位二进制补码,带符号位扩展,分为低字节、高字节两个字节。

三、完整通信时序(核心!驱动成败关键点)

3.1 复位时序(初始化,每次通信必须先复位)

复位作用:主机和 DS18B20 握手,确认传感器在线可通信。 步骤:

  1. 主机将总线拉低 480‑960μs,发送复位脉冲;
  2. 主机释放总线,延时15‑60μs,等待从机应答;
  3. DS18B20 如果存在,主动把总线拉低 60‑240μs,输出响应脉冲;
  4. DS18B20 释放总线,总线回到高电平,初始化完成。

如果第 3 步没有拉低应答脉冲:硬件接线错误、缺少上拉电阻、时序延时不对。

3.2 写时序(主机向传感器写 bit)

写 0、写 1 区别在于主机拉低总线持续时间,DS18B20 在 15‑60μs 窗口采样总线电平。

✅ 写 0 时序

  1. 主机拉低总线,维持60~120μs;
  2. DS18B20 在 15‑60μs 采样,检测到低电平代表写入 0;
  3. 主机释放总线。

✅ 写 1 时序

  1. 主机拉低总线小于 15μs,立刻释放总线;
  2. DS18B20 采样得到高电平,代表写入 1。

一个字节就是循环 8 次写 bit,低位优先发送。

3.3 读时序(主机读取传感器 bit)

读操作全部由主机发起拉低脉冲,必须在 15μs 以内完成电平采样,超时采样会读到错误电平CSDN博...。

✅ 读 1 时序

  1. 主机拉低总线 > 1μs,马上释放总线;
  2. DS18B20 释放总线,总线为高电平;
  3. 主机15μs 之内采样总线为高电平 → 读到 1。

✅ 读 0 时序

  1. 主机拉低总线 > 1μs,马上释放总线;
  2. DS18B20 主动把总线拉低;
  3. 主机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℃。

六、开发踩坑总结

  1. 时序必须严格微秒级延时,晶振不同,delay_us延时函数要校准;
  2. 读时序采样窗口只有 15μs,采样动作不能拖到 15μs 之后;
  3. 启动转换 0x44 之后,必须等待转换时间,不能立刻读;
  4. 单总线必须上拉电阻,否则总线电平异常,无应答;
  5. 单传感器才可以使用0xCC跳过 ROM;多个 DS18B20 挂总线禁止使用 0xCC;
  6. 负数一定要做补码转换,否则负温读数完全错乱。

七、核心函数伪代码参考

复制代码
//复位
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;
    }
}
相关推荐
Ruiery5 小时前
Linux 6.6内核内存管理深度解析(一):物理内存初始化 — memblock 怎么把内存交给 buddy
linux·运维·服务器
天蓝蓝的本我5 小时前
conda日常用到的命令积累1-登录linux,安装pycharm
linux·pycharm·conda
Android系统攻城狮6 小时前
Linux Gstreamer深度解析之gst_audio_encoder_get_frame_max调用流程与实战(五十九)
linux·运维·服务器·gstreamer音视频·音视频进阶·gstreamer音视频进阶
女神下凡6 小时前
芯参谋(41):DDR2_电路设计指南
arm开发·单片机·嵌入式硬件·设计规范
忆挽篱笙歌6 小时前
makefil
linux·运维·服务器
菜_小_白7 小时前
codex
linux·vscode·ai
zhangrelay8 小时前
用ROS2Lyrical实验报告册思路重做蓝桥云课ROS1实验并改进
linux·笔记·学习·ubuntu·机器人
林兴洋8 小时前
linux-mtr命令-ping和traceroute的能力合二为一
linux
OsDepK8 小时前
OSMDE_v1.9.0已加入FTP与shell功能
linux·运维·服务器
国科安芯8 小时前
商业立方星平台中高集成度抗辐射MCU的功耗优化与批量化应用可行性探讨
单片机·嵌入式硬件·架构·risc-v·抗辐射·as32x601