自学嵌入式day48,温度传感器

51单片机驱动DS18B20温度传感器笔记

1. DS18B20简介

  • 单总线(1-Wire)接口: 仅需一根数据线即可完成通信(外加电源和地线),支持多个器件挂接在同一条总线上。
  • 数字输出: 直接输出数字温度值,省去复杂的信号调理电路。
  • 精度: 典型精度为\\pm0.5\^{\\circ}C-10\^{\\circ}C+85\^{\\circ}C范围内)。
  • 分辨率: 可编程为9、10、11或12位,对应温度分辨率分别为0.5\^{\\circ}C0.25\^{\\circ}C0.125\^{\\circ}C0.0625\^{\\circ}C。默认为12位。
  • 温度范围: -55\^{\\circ}C+125\^{\\circ}C
  • 供电: 支持寄生供电(仅需GND和DQ两根线)或外部供电(需VDD、GND、DQ三根线)。寄生供电时,需在DQ线上接一个约4.7KΩ的上拉电阻。

2. 硬件连接 (以外部供电为例)

  • 51单片机:
    • Px.y (某个IO口) 连接至 DS18B20 的 DQ (数据线)。
    • VCC 连接至 DS18B20 的 VDD
    • GND 连接至 DS18B20 的 GND
  • DS18B20:
    • VDD 接 +5V电源。
    • GND 接地。
    • DQ 接单片机IO口,并通过一个 4.7KΩ 的上拉电阻连接到 VDD

3. 单总线通信协议要点

通信由单片机主机发起和控制,包括初始化、ROM命令、功能命令、数据传输。所有通信均以**时隙(Time Slot)**为单位。

  • 初始化序列 (复位脉冲 + 存在脉冲)

    • 主机拉低DQ线至少480μs(复位脉冲)。
    • 主机释放DQ线(上拉电阻拉高)。
    • DS18B20等待15-60μs后,拉低DQ线60-240μs(存在脉冲),表示响应。
    • 主机检测到存在脉冲后,知道总线上有器件。
  • 写时隙

    • 写'0'时隙: 主机拉低DQ线,并保持低电平至少60μs(通常在60-120μs)。
    • 写'1'时隙: 主机拉低DQ线,然后在15μs内释放DQ线(上拉拉高),并保持高电平直到时隙结束(总时隙时间至少60μs)。
    • 每个写时隙只能写入1位数据,先写最低位(LSB)。
  • 读时隙

    • 主机拉低DQ线至少1μs。
    • 主机释放DQ线(上拉拉高)。
    • 主机在拉低后的15μs内采样DQ线电平。
      • 低电平:表示DS18B20发送了'0'。
      • 高电平:表示DS18B20发送了'1'。
    • 整个读时隙应大于60μs。
    • 每个读时隙只能读取1位数据,先读最低位(LSB)。
  • ROM命令 (识别总线上器件)

    • 0x33 - Read ROM (读ROM,仅单器件时用)。
    • 0x55 - Match ROM (匹配ROM,用于选择特定器件)。
    • 0xCC - Skip ROM (跳过ROM,总线只有一个器件或向所有器件广播命令时用)。
  • 功能命令 (操作DS18B20)

    • 0x44 - Convert T (启动温度转换)。
    • 0xBE - Read Scratchpad (读暂存器,读取温度值和配置)。
    • 0x4E - Write Scratchpad (写暂存器,写TH、TL和配置寄存器)。
    • 0x48 - Copy Scratchpad (复制暂存器内容到EEPROM)。
    • 0xB8 - Recall EEPROM (将EEPROM内容召回至暂存器)。
    • 0xB4 - Read Power Supply (读供电模式)。

4. 读取温度流程 (以跳过ROM为例)

  1. 初始化: 发送复位脉冲,检测存在脉冲。
  2. 跳过ROM: 发送命令 0xCC
  3. 启动转换: 发送命令 0x44
    • 转换时间取决于分辨率:12位时约需750ms。在此期间,主机可以查询总线状态或等待。
  4. 初始化: 再次发送复位脉冲,检测存在脉冲。
  5. 跳过ROM: 发送命令 0xCC
  6. 读暂存器: 发送命令 0xBE
  7. 读取数据: 连续读取9字节(或只读前2字节温度值)。
    • 第0字节:温度值低字节(LS Byte)。
    • 第1字节:温度值高字节(MS Byte)。
  8. 计算温度:
    • 将高低字节合并成一个16位整数 TempRaw
    • 温度值以 1/16\^{\\circ}C 为单位(12位分辨率时)。
    • 实际温度 T $$ T = \frac{\text{TempRaw}}{16} $$
    • 注意:TempRaw 的最高位(bit15)是符号位。0表示正温度,1表示负温度(以补码形式存储)。
      • 负温度处理:TempRaw = TempRaw - 0xFFFF - 1 或取反加一后再计算。
c 复制代码
#include <REGX51.H>
#include <INTRINS.H> // 用于_nop_()延时

sbit DQ = P1^0; // 假设DS18B20数据线接在P1.0

// 延时函数 (需根据实际晶振频率调整)
void Delay_us(unsigned int us) {
    while (us--);
}

// 初始化 (复位 + 检测存在)
bit DS18B20_Init() {
    bit ack;
    DQ = 1; // 释放总线
    Delay_us(5);
    DQ = 0; // 主机拉低总线 (复位脉冲)
    Delay_us(480); // 保持480us以上低电平
    DQ = 1; // 释放总线,等待上拉拉高
    Delay_us(60); // 等待15-60us后采样
    ack = DQ; // 读取存在脉冲 (ack=0表示存在)
    Delay_us(420); // 等待剩余时隙时间 (总时隙>480us)
    return !ack; // 返回1表示初始化成功
}

// 写一个字节 (低位在前)
void DS18B20_WriteByte(unsigned char dat) {
    unsigned char i;
    for (i = 0; i < 8; i++) {
        DQ = 0; // 拉低总线开始写时隙
        _nop_(); // 短暂延时 (约1us)
        DQ = dat & 0x01; // 输出当前位 (最低位)
        Delay_us(60); // 保持60us以上 (写'0'时保持低,写'1'时会被释放)
        DQ = 1; // 释放总线
        dat >>= 1; // 准备下一位
        Delay_us(5); // 时隙间恢复时间
    }
}

// 读一个字节 (低位在前)
unsigned char DS18B20_ReadByte() {
    unsigned char i, dat = 0;
    for (i = 0; i < 8; i++) {
        DQ = 0; // 拉低总线开始读时隙
        _nop_(); // 短暂延时 (约1us)
        DQ = 1; // 释放总线,准备采样
        _nop_(); // 短暂延时 (约5-10us)
        if (DQ) dat |= (0x01 << i); // 在15us内采样,若为高则置位相应位
        Delay_us(50); // 等待该时隙剩余时间 (总时隙>60us)
    }
    return dat;
}

// 获取温度值 (简化流程)
float DS18B20_GetTemp() {
    unsigned char TL, TH;
    int TempRaw;
    float T;

    if (!DS18B20_Init()) return 0; // 初始化失败
    DS18B20_WriteByte(0xCC); // Skip ROM
    DS18B20_WriteByte(0x44); // Convert T
    // 此处应等待转换完成 (可延时750ms 或 查询总线状态)
    Delay_ms(750); // 简单延时等待转换 (需实现ms级延时函数)

    if (!DS18B20_Init()) return 0; // 再次初始化
    DS18B20_WriteByte(0xCC); // Skip ROM
    DS18B20_WriteByte(0xBE); // Read Scratchpad
    TL = DS18B20_ReadByte(); // 读取温度低字节
    TH = DS18B20_ReadByte(); // 读取温度高字节
    // 可以继续读取其他字节,但这里只关心温度

    TempRaw = (TH << 8) | TL; // 合成16位温度原始值
    T = (float) TempRaw * 0.0625; // 乘以分辨率 (1/16 = 0.0625)
    return T;
}

注意事项:

  • 延时精度: 单总线协议对时序要求严格。延时函数 (Delay_us, Delay_ms) 必须根据单片机实际晶振频率精确调整。_nop_() 用于产生极短延时(1个机器周期)。
  • 上拉电阻: 必须连接约4.7KΩ的上拉电阻到DQ线。
  • 总线负载: 总线上的器件数量会影响信号质量。
  • 负温度处理: 代码示例未处理负温度(当TH的最高位为1时表示负温度),实际应用中需完善。
  • 等待转换完成: 除了延时等待,更优的方法是主机在启动转换后,不断发送读时隙,直到DS18B20返回'0'(表示转换完成)或'1'(表示仍在转换)。
  • 寄生供电: 若使用寄生供电,在温度转换期间(特别是高分辨率时),主机需通过上拉电阻给总线提供足够的电流(强上拉),转换完成后恢复弱上拉。
相关推荐
电子绿洲1 小时前
什么是红外接收头?红外遥控系统核心元件基础知识解析
单片机·嵌入式硬件·智能硬件·硬件电路·硬件设计
乡野码圣2 小时前
【RK3588 Android12】开发效率提升技巧
android·嵌入式硬件
蓁蓁啊2 小时前
GCC 头文件搜索路径:-I vs -idirafter 深度解析
java·前端·javascript·嵌入式硬件·物联网
Xx香菜4 小时前
单片机—4
单片机·嵌入式硬件
VekiSon4 小时前
51单片机——GPIO、按键、中断、定时器与PWM
单片机·嵌入式硬件·51单片机
纳祥科技4 小时前
NX3302,3进1出HDMI/DVI视频切换器芯片,兼容LT8631UX
单片机·嵌入式硬件·音视频
析木不会编程4 小时前
51单片机程序下载逻辑
单片机·嵌入式硬件·51单片机
羊小猪~~4 小时前
【QT】-- QT基础类
开发语言·c++·后端·stm32·单片机·qt
自激振荡器4 小时前
第二天:IIC总线协议
单片机·嵌入式·通信协议·iic总线协议