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;
    }
}
相关推荐
j7~1 小时前
【Linux网络加餐】(篇六)网络版计算器(上):模板方法模式、序列化与 JSON
linux·c++·json·序列化·反序列化·网络版计算机
智购无人售货机厂家1 小时前
2026自动售货机品类拓展逻辑:从饮料零食到鲜食药品文创的工程实践~YH
服务器·人工智能·单片机·线性代数·矩阵
流浪0011 小时前
Linux系统篇34——信号(六):信号处理期间又来了怎么办?——sigaction、sa_mask、可重入函数与 volatile
linux·运维·面试·操作系统·信号处理·信号
学烹饪的小胡桃2 小时前
资产设备管理系统 WGFIX 怎么设置https访问
linux·运维·服务器·网络·安全
ElfBoard2 小时前
作品展示|基于RK3588的复杂空间下自主导航无人机与多传感器 AI 融合环境监测分析
大数据·人工智能·单片机·嵌入式硬件·团队开发
星源~2 小时前
MCU-OTA升级的flash分散加载应用
单片机·嵌入式·ota·flash分散加载
邪修king2 小时前
Re:Linux系统篇(二十六):文件系统(二):Ext 文件系统底层详解:从 inode、块组到软硬链接,结合 Windows 讲透文件管理本质
android·java·linux
单片机仿真设计2 小时前
【proteus仿真】基于 STM32 单片机农业灾害监测系统(仿真图+程序)
stm32·单片机·嵌入式硬件·proteus
高亦真2 小时前
今天是学习嵌入式的第38天
linux·学习·算法