当前位置: 首页 > news >正文

DS18B20 单总线(1-Wire)协议:UART 模拟篇

在嵌入式开发中,DS18B20 是单总线协议的典型代表。由于单总线对时序要求极严(微秒级),传统 GPIO 翻转易受中断干扰。本文重点介绍如何通过 UART(串口)硬件 完美模拟 1-Wire 时序。

一、什么是单总线(1-Wire)?

单总线(1-Wire)是由 Dallas(现 Maxim)开发的异步半双工通信协议。

  • 极简连线:最少连线仅需 一根数据线(DQ)+ GND。
  • 物理特性:采用 开漏输出(Open Drain),通过外部上拉电阻(通常 4.7kΩ)保证空闲时总线为高电平。
  • 主从结构:主机发起,从机响应。
  • 唯一标识:每个从机出厂自带全球唯一的 64 位 ROM ID,支持一根线上挂载多个传感器。
  • 时序敏感:通信时序要求严格,主机必须精确控制拉低和释放总线的时间。

二、通信基本流程

一次完整通信包含以下步骤:

1. 初始化(Reset + Presence)

  • 主机拉低 ≥ 480µs(Reset)
  • 释放总线
  • 从机等待 15~60µs 后拉低 60~240µs(Presence)

表示设备在线并准备通信

2. 发送 ROM 命令

用于设备寻址:

命令功能
Read ROM (33h)读取唯一ID(单设备)
Match ROM (55h)选择指定设备
Skip ROM (CCh)跳过寻址(单设备)
Search ROM (F0h)搜索所有设备
Alarm Search (ECh)搜索报警设备

3. 发送功能命令

针对设备内部功能操作:

命令功能
Convert T (44h)启动温度转换
Read Scratchpad (BEh)读取数据
Write Scratchpad (4Eh)写配置
Copy Scratchpad (48h)写入 EEPROM
Recall E2 (B8h)读取 EEPROM
Read Power Supply (B4h)查询供电方式

4. 数据读写

写时序:

  • 写 0:拉低时间长(60 ~ 120µs)
  • 写 1:拉低时间短(1~15µs)

读时序:

  • 主机拉低后释放
  • 从机决定电平:
    • 低 → 0
    • 高 → 1

三、UART模拟单总线通信原理

利用 UART 的起始位(Start Bit)始终为低电平,以及数据位可控的特性,通过切换波特率来模拟 1-Wire 的各种脉冲。

硬件连接:UART 的 TX 和 RX 必须短接(Half-Duplex 模式或物理短接),并连接一个上拉电阻 到 3.3V。

1. 复位与存在检测(波特率:9600)

  • 原理:9600 下 1 个 Bit 约为 104µs。
  • 发送 0xF0:
    • 时序:1 个起始位(0) + 4 个数据位(0) + 4 个数据位(1) + 1 个停止位(1)。
    • 低电平时长:(满足 Reset 要求的 >480µs)。
    • 高电平释放期:后 5 个 bit 为高,DS18B20 会在此期间拉低总线产生 Presence(存在信号)。
  • 判断逻辑:若 Receive != 0xF0,说明有从机拉低了总线,传感器在线。

2. 位读写(波特率:115200)

  • 原理:115200 下 1 个 Bit 约为 8.68µs。
操作UART 发送字节信号成分低电平总时长1-Wire 标准要求
写 1 / 读请求0xFF仅起始位为 08.68µs1 ~ 15µs
写 00x00起始位 + 8位数据全 078.12µs60 ~ 120µs

四、代码示例

1. 单个设备代码示例:

// 初始化 UART 波特率的辅助函数 static void DS18B20_UART_ReInit(uint32_t baudrate) { huart2.Init.BaudRate = baudrate; HAL_UART_Init(&huart2); } // 发送并接收一个位 (115200bps) static uint8_t DS18B20_WriteRead_Bit(uint8_t bit_val) { uint8_t tx_data = bit_val ? 0xFF : 0x00; // 发送 0xFF 代表释放总线读 1,0x00 代表拉低读 0 uint8_t rx_data = 0; HAL_UART_Transmit(&huart2, &tx_data, 1, 10); HAL_UART_Receive(&huart2, &rx_data, 1, 10); return (rx_data == 0xFF) ? 1 : 0; // 如果收回也是 0xFF,说明总线被拉高,读到 1 } // 发送一个字节 (8位) static void DS18B20_WriteByte(uint8_t data) { for (int i = 0; i < 8; i++) { DS18B20_WriteRead_Bit(data & 0x01); data >>= 1; } } // 读取一个字节 (8位) static uint8_t DS18B20_ReadByte(void) { uint8_t data = 0; for (int i = 0; i < 8; i++) { if (DS18B20_WriteRead_Bit(1)) { // 发送 1 释放总线,读取回复 data |= (1 << i); } } return data; } // 3. 读取完整温度 float DS18B20_GetTemp(void) { uint8_t data[2]; uint8_t presence_echo = 0; uint8_t reset_cmd = 0xF0; // --- 1. 启动转换 --- DS18B20_UART_ReInit(9600); HAL_UART_Transmit(&huart2, &reset_cmd, 1, 10); HAL_UART_Receive(&huart2, &presence_echo, 1, 10); if (presence_echo == 0xF0) return -101.0; // 没检测到传感器 DS18B20_UART_ReInit(115200); DS18B20_WriteByte(0xCC); // Skip ROM DS18B20_WriteByte(0x44); // Convert T HAL_Delay(750); // 等待转换 // --- 2. 读取结果 (必须重新 Reset) --- DS18B20_UART_ReInit(9600); HAL_UART_Transmit(&huart2, &reset_cmd, 1, 10); HAL_UART_Receive(&huart2, &presence_echo, 1, 10); if (presence_echo == 0xF0) return -102.0; DS18B20_UART_ReInit(115200); DS18B20_WriteByte(0xCC); // Skip ROM DS18B20_WriteByte(0xBE); // Read Scratchpad data[0] = DS18B20_ReadByte(); // LSB data[1] = DS18B20_ReadByte(); // MSB int16_t temp_raw = (data[1] << 8) | data[0]; return temp_raw * 0.0625f; }

2. 多设备支持

如果总线上有多个设备,必须使用 Match ROM 或 Search ROM 来区分不同设备。

  • 匹配ID读取:
DS18B20_UART_ReInit(115200); DS18B20_WriteByte(0x55); // Match ROM 指令 DS18B20_WriteROM(ROM_IDs[rom_id]); // 发送指定的 8 字节 ID DS18B20_WriteByte(0xBE); // Read Scratchpad

在正式布线先,可以逐个接入传感器以确认 ID,或使用 Search ROM 命令扫描总线上的所有设备。

  • 读取单个设备的 ROM ID 示例:
void DS18B20_Read_Single_ROM(void) { // 1. 复位 (9600 bps) DS18B20_UART_ReInit(9600); uint8_t reset_cmd = 0xF0; uint8_t echo; HAL_UART_Transmit(&huart2, &reset_cmd, 1, 10); HAL_UART_Receive(&huart2, &echo, 1, 10); uint8_t current_id[8]; if (echo != 0xF0) { // 检测到设备 // 2. 发送 Read ROM 命令 (0x33h) @ 115200 bps DS18B20_UART_ReInit(115200); DS18B20_WriteByte(0x33); // 3. 连续读取 8 个字节 for (int i = 0; i < 8; i++) { current_id[i] = DS18B20_ReadByte(); } // 4. 打印出来 (假设你已经配置好了 printf) printf("ROM ID: "); for (int i = 0; i < 8; i++) { printf("%02X ", current_id[i]); } printf("\r\n"); } else { printf("No Sensor Found!\r\n"); } }
http://www.jsqmd.com/news/512709/

相关文章:

  • 2026年南京口碑好的日立空调售后服务推荐,专业维修与保养全解析 - 工业品网
  • GPT-5.4降价血战:mini当老大,nano做小弟,独立开发者的省钱攻略
  • 基于博途1200PLC+HMI的‘大小球分拣控制系统仿真‘工程
  • 探讨日立空调售后靠谱吗,张尤达全品牌服务有保障 - 工业品牌热点
  • 本地部署openclaw
  • 响应式设计的核心:深入理解CSS媒体查询
  • 从静态检索到动态记忆:面向长篇 AI 写作的一种 Memory-First 架构思路
  • 分析服务不错的日立空调售后服务,南京有哪些品牌性价比高 - 工业推荐榜
  • 终于在红磡必嘉坊,找到了香港生活的“最优解”:首匯 Chester 置业笔记
  • MySQL安全加固十大硬核操作技术
  • JS消除异步传染性
  • 2026年日立空调选购后售后保障,资质齐全24小时服务电话是啥 - myqiye
  • IT疑难杂症诊疗室
  • 模板方法模式:复杂业务代码的解耦与复用之道
  • 阿里云代理商:阿里云无影云电脑部署 OpenClaw 接入钉钉机器人全攻略
  • 动态调整转弯率才是灵魂所在
  • UG CAM加工二次开发,型腔铣CAVITY_MILL设置 切削参数-刀路方向 向内、向外API方法
  • 分布式AI Coding: Claude Code 系统架构与技术方案设计文档 1
  • 2026揭阳雄盛橄榄酒选购支招,实力与客户反馈能满足自饮不 - mypinpai
  • 写论文如何又快又好?资深教授推荐这几个AI写作辅助软件
  • 广州钡源:电源模块5大常见故障及成因分析
  • 实用工具分享:让论文图表、数据表述更专业的AI写作辅助软件
  • python基础第一课(自行下好pycharm,并进行练习)
  • 2026年国贤府PARK深度解析:从政企共建模式看未来社区发展新范式推荐 - 十大品牌推荐
  • Comsol光学仿真模型:纳米球/柱Mie散射多级分解
  • 从入门到精通:InkCanvas作为网课演示利器的完整使用指南
  • 高频方波电压注入IPMSM无感控制算法Simulink仿真调试与实际应用探索
  • 《数据结构与算法》-- 数据结构的通识
  • 三相不平衡电网条件下PWM整流电路仿真模型与双闭环控制策略研究
  • 半颗星教育电话查询:培训课程咨询与学习路径解析 - 十大品牌推荐