欢迎光临
我们一直在努力

学习笔记——DS18B20 温度传感器

DS18B20 温度传感器

一、传感器概述

1.1 基本特性

DS18B20 是由 Dallas Semiconductor(现 Maxim Integrated)生产的数字温度传感器。该器件采用单总线接口,可直接输出数字温度值,无需外部模数转换电路。

关键参数表:

参数类别技术规格
温度测量范围 -55℃ 至 +125℃
测量精度 ±0.5℃(-10℃ 至 +85℃范围内)
分辨率 可编程配置:9、10、11、12 位
默认分辨率 12 位(0.0625℃/LSB)
工作电压 3.0V 至 5.5V
转换时间 93.75ms(9位)至 750ms(12位)
封装形式 TO-92、SO-8、µSOP

1.2 引脚定义

TO-92 封装引脚排列(正视,引脚朝下):

引脚功能说明:

  • 引脚1(GND):电源地,连接至系统参考地

  • 引脚2(DQ):单总线数据输入/输出引脚

  • 引脚3(VDD):电源输入引脚(3.0V-5.5V)

二、单总线通信协议

2.1 协议概述

单总线协议(1-Wire Protocol)采用单根数据线实现双向通信。该协议包含以下关键技术特性:

  • 单主多从架构:单总线上可挂接多个从设备

  • 寄生供电模式:通过数据线为设备供电,无需独立电源

  • 严格的时序要求:所有通信操作都有精确的时序规范

  • 2.2 电气特性

    典型应用电路:
    VCC (+3.3V-5V)

    ├─[4.7kΩ]─┐
    │ │
    └─────┐ │
    │ │
    DS18B20 │
    1│ 2│ 3│
    GND DQ VDD
    │ │
    GND ├─→ MCU I/O Pin

    GND

    上拉电阻作用:

    • 在总线空闲时提供确定的高电平状态

    • 确保信号完整性,减少噪声影响

    • 典型值:4.7kΩ ±5%

    三、温度数据格式

    3.1 温度寄存器结构

    DS18B20 输出 16 位二进制补码格式的温度数据:

    位位置1514131211109876543210
    含义 S S S S S 2⁶ 2⁵ 2⁴ 2⁰ 2⁻¹ 2⁻² 2⁻³ 2⁻⁴

    说明:

    • 位 15-11:符号位(S=1 表示负温度,S=0 表示正温度)

    • 位 10-4:整数部分(7 位二进制,范围 0-127)

    • 位 3-0:小数部分(4 位二进制)

    3.2 分辨率配置

    DS18B20 提供四种分辨率设置,通过配置寄存器实现:

    分辨率位数R1R0温度精度最大转换时间
    9 位 0 0 0.5℃ 93.75ms
    10 位 0 1 0.25℃ 187.5ms
    11 位 1 0 0.125℃ 375ms
    12 位 1 1 0.0625℃ 750ms

    默认配置:R1=1, R0=1(12 位分辨率)

    四、通信时序详析

    4.1 复位脉冲时序

    时间参数要求:

    • 主机复位脉冲宽度:最小 480μs

    • 主机释放总线后延迟:15-60μs

    • 从机响应脉冲宽度:60-240μs

    • 总线恢复时间:最小 480μs

    4.2 写时序规范

    写"0"时序:

    • 主机将总线拉低至少60us

    • ds18b20在60us内去采样,采到低电平,则代表主机向ds18b20发送了一个bit'0'

    • 最后主机将总线拉高

    写"1"时序:

    • 主机将总线拉低大于1us

    • 主机释放总线,将总线拉高

    • 主机延时至少45us,确保ds18b20能够采样到一个高电平

    写时间槽参数:

    • 写"0"低电平时间:60-120μs

    • 写"1"低电平时间:1-15μs

    • 写周期总时间:最小 60μs,典型 70μs

    4.3 读时序规范

    读时间槽参数:

    • 主机低电平时间:>1μs

    • 采样窗口:低电平释放后 15μs 内

    • 位周期总时间:最小 60μs

    五、驱动程序实现

    5.1 硬件抽象层定义

    // 引脚操作宏定义
    #define DS18B20_PORT P3 // 使用P3端口
    #define DS18B20_PIN 7 // 使用P3.7引脚

    // 总线操作宏
    #define DQ_LOW() (DS18B20_PORT &= ~(1 << DS18B20_PIN))
    #define DQ_HIGH() (DS18B20_PORT |= (1 << DS18B20_PIN))
    #define DQ_INPUT() (DS18B20_PORT |= (1 << DS18B20_PIN)) // 设置为输入模式
    #define DQ_READ() ((DS18B20_PORT & (1 << DS18B20_PIN)) ? 1 : 0)

    5.2 精确延时函数

    /**
    * @brief 微秒级延时函数
    * @param us 延时微秒数
    * @note 基于11.0592MHz晶振,12时钟周期
    */
    void delay_us(unsigned int us)
    {
    while(us–)
    {
    _nop_(); _nop_(); _nop_();
    _nop_(); _nop_(); _nop_();
    _nop_(); _nop_(); _nop_();
    }
    }

    /**
    * @brief 毫秒级延时函数
    * @param ms 延时毫秒数
    */
    void delay_ms(unsigned int ms)
    {
    while(ms–)
    {
    delay_us(1000);
    }
    }

    5.3 复位函数实现

    /**
    * @brief DS18B20复位序列
    * @return 1:复位成功,检测到器件存在
    * 0:复位失败,器件无响应
    */
    uint8_t DS18B20_Reset(void)
    {
    uint8_t presence = 0;

    // 主机驱动总线为低电平
    DQ_LOW();

    // 保持低电平480μs以上(推荐500-550μs)
    delay_us(550);

    // 主机释放总线,上拉电阻拉至高电平
    DQ_HIGH();
    DQ_INPUT(); // 切换为输入模式

    // 延时等待15-60μs
    delay_us(30);

    // 检测从机响应脉冲
    if(DQ_READ() == 0)
    {
    // 等待从机释放总线(60-240μs)
    uint16_t timeout = 250;
    while(!DQ_READ() && timeout–);

    if(timeout > 0)
    {
    presence = 1; // 检测到器件
    }
    }

    // 等待总线恢复(至少480μs)
    delay_us(500);

    return presence;
    }

    5.4 数据读写函数

    /**
    * @brief 向DS18B20写入一个字节
    * @param data 要写入的数据字节
    */
    void DS18B20_WriteByte(uint8_t data)
    {
    uint8_t i;

    for(i = 0; i < 8; i++)
    {
    // 写时间槽开始
    DQ_LOW();

    if(data & 0x01) // 写入"1"
    {
    // 保持低电平>1μs,然后释放总线
    _nop_(); _nop_(); // 约2μs延时
    DQ_HIGH();
    DQ_INPUT();

    // 保持总线高电平至少45μs
    delay_us(50);
    }
    else // 写入"0"
    {
    // 保持低电平60-120μs
    delay_us(70);
    DQ_HIGH();
    DQ_INPUT();
    }

    // 写时间槽结束,恢复总线
    data >>= 1; // 准备下一位
    delay_us(5); // 位间恢复时间
    }

    // 字节写入完成后,确保总线处于释放状态
    DQ_HIGH();
    DQ_INPUT();
    }

    /**
    * @brief 从DS18B20读取一个字节
    * @return 读取到的数据字节
    */
    uint8_t DS18B20_ReadByte(void)
    {
    uint8_t i;
    uint8_t data = 0;

    for(i = 0; i < 8; i++)
    {
    // 读时间槽开始
    DQ_LOW();
    _nop_(); _nop_(); // 约2μs低电平

    // 主机释放总线,准备采样
    DQ_HIGH();
    DQ_INPUT();

    // 延时15μs后采样
    delay_us(15);

    // 读取总线状态
    if(DQ_READ())
    {
    data |= (0x01 << i); // 读取到"1"
    }

    // 完成读时间槽(总时间>60μs)
    delay_us(45);

    // 确保总线恢复
    DQ_HIGH();
    DQ_INPUT();
    }

    return data;
    }

    5.5 温度读取完整流程

    /**
    * @brief 读取当前温度值
    * @return 温度值(浮点数,单位:℃)
    * @note 使用12位分辨率,转换时间约750ms
    */
    float DS18B20_ReadTemperature(void)
    {
    uint8_t temp_low, temp_high;
    int16_t temp_raw;
    float temperature;

    // 步骤1:启动温度转换
    if(!DS18B20_Reset())
    {
    return ERROR_TEMPERATURE; // 定义错误值,如-999.0
    }

    // 发送跳过ROM命令(仅单设备情况)
    DS18B20_WriteByte(0xCC);

    // 发送温度转换命令
    DS18B20_WriteByte(0x44);

    // 等待转换完成(12位分辨率需750ms)
    delay_ms(750);

    // 步骤2:读取温度数据
    if(!DS18B20_Reset())
    {
    return ERROR_TEMPERATURE;
    }

    // 发送跳过ROM命令
    DS18B20_WriteByte(0xCC);

    // 发送读暂存器命令
    DS18B20_WriteByte(0xBE);

    // 读取温度寄存器(低字节和高字节)
    temp_low = DS18B20_ReadByte();
    temp_high = DS18B20_ReadByte();

    // 合成16位温度原始值
    temp_raw = (temp_high << 8) | temp_low;

    // 步骤3:温度值转换
    // 判断温度符号
    if(temp_raw & 0x8000) // 负温度
    {
    // 计算补码的绝对值
    temp_raw = ~temp_raw + 1;
    temperature = -(temp_raw * 0.0625);
    }
    else // 正温度
    {
    temperature = temp_raw * 0.0625;
    }

    return temperature;
    }

    七、调试与故障排除

    7.1 常见问题及解决方案

    问题现象可能原因解决方案
    读取温度始终为0 总线无上拉电阻 添加4.7kΩ上拉电阻至VCC
    温度值异常波动 电源噪声干扰 在VDD和GND间添加100nF电容
    器件无响应 时序不符合规范 使用逻辑分析仪检查时序
    温度转换失败 延时不足 确保750ms转换等待时间
    多个传感器冲突 ROM未正确匹配 实现ROM搜索和匹配算法

    八、技术参数总结表

    技术指标规格描述
    通信接口 单总线(1-Wire)
    数据格式 16位二进制补码
    转换精度 用户可编程9-12位
    最大采样率 9位:约10.6Hz,12位:约1.33Hz
    总线负载能力 理论上最多可挂接数百个器件
    温度误差 ±0.5℃(-10℃至+85℃)
    长期稳定性 ±0.2℃/年(典型值)
    ESD保护 人体模型:≥4kV
    赞(0)
    未经允许不得转载:171主机测评 » 学习笔记——DS18B20 温度传感器
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址