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

STM32 DS18B20 多点测温实战:1条总线挂载3个传感器与ROM搜索算法

STM32 DS18B20 多点测温实战:1条总线挂载3个传感器与ROM搜索算法

在工业温室监控、机房温度巡检等场景中,分布式温度监测系统往往需要同时采集多个位置的温度数据。传统单传感器方案需要占用大量GPIO资源,而DS18B20凭借其独特的单总线协议,允许在同一条数据线上挂载多个传感器。本文将深入解析如何基于STM32实现单总线挂载3个DS18B20传感器的完整解决方案,包含ROM地址搜索算法、数据帧结构设计以及总线冲突规避策略。

1. DS18B20多点测温系统架构设计

1.1 单总线网络拓扑优势分析

DS18B20采用单总线(1-Wire)通信协议,仅需一根数据线即可完成供电和数据传输(寄生供电模式下甚至无需额外电源线)。这种特性使得构建多点测温系统时具有显著优势:

  • 布线简化:3个传感器共用同一组DQ总线,GPIO占用减少66%
  • 扩展灵活:理论单总线可挂载多达100个传感器(实际受总线电容限制)
  • 成本优化:省去多路ADC或I2C/SPI扩展芯片

典型的多点测温系统硬件连接如下图所示:

VDD (3.3V) | R (4.7KΩ) | STM32 GPIO_PA1 ---+--- DQ (总线) | | | DS1 DS2 DS3 GND GND GND

1.2 关键挑战与解决方案

实现稳定可靠的多点测温需要解决以下核心问题:

挑战点解决方案
传感器地址识别ROM搜索算法实现
数据隔离与匹配64位ROM地址校验机制
总线时序冲突严格时序控制+重试机制
供电稳定性强上拉电阻配置(寄生供电时)

2. ROM地址搜索算法实现

2.1 64位ROM编码结构解析

每个DS18B20内置全球唯一的64位光刻ROM编码,其结构如下:

typedef struct { uint8_t family_code; // 固定0x28 uint8_t serial[6]; // 48位唯一序列号 uint8_t crc; // 前56位的CRC校验 } DS18B20_ROM_Code;

2.2 二叉树搜索算法实现

通过SEARCH_ROM(0xF0)命令配合位处理实现地址搜索,关键步骤如下:

  1. 初始化搜索

    void DS18B20_InitSearch(void) { memset(search_state.last_discrepancy, 0, sizeof(search_state.last_discrepancy)); search_state.last_device_flag = false; }
  2. 递归搜索过程

    bool DS18B20_SearchNext(uint8_t *rom_code) { uint8_t id_bit, cmp_id_bit; uint8_t search_direction; uint8_t rom_byte_mask = 1; uint8_t rom_byte_index = 0; if (!search_state.last_device_flag) { // 发送SEARCH_ROM命令 OneWire_Reset(); OneWire_WriteByte(0xF0); do { // 读取两个数据位 id_bit = OneWire_ReadBit(); cmp_id_bit = OneWire_ReadBit(); if (id_bit && cmp_id_bit) break; // 无设备响应 // 确定搜索方向 if (id_bit != cmp_id_bit) { search_direction = id_bit; } else { // 冲突处理 if (rom_byte_index < search_state.last_discrepancy) { search_direction = (rom_code[rom_byte_index] & rom_byte_mask) > 0; } else { search_direction = (rom_byte_index == search_state.last_discrepancy); } if (!search_direction) search_state.last_discrepancy = rom_byte_index; } // 写入搜索方向位 OneWire_WriteBit(search_direction); rom_code[rom_byte_index] |= (search_direction << (rom_byte_mask-1)); rom_byte_mask <<= 1; if (rom_byte_mask == 0) { rom_byte_index++; rom_byte_mask = 1; } } while (rom_byte_index < 8); return (rom_byte_index >= 8); } return false; }

2.3 ROM地址管理策略

建议在系统初始化阶段完成所有传感器的ROM地址搜索,并建立地址映射表:

#define MAX_SENSORS 3 DS18B20_ROM_Code sensor_rom[MAX_SENSORS]; void DiscoverAllSensors(void) { uint8_t found = 0; DS18B20_InitSearch(); while(found < MAX_SENSORS && DS18B20_SearchNext((uint8_t*)&sensor_rom[found])) { if (OneWire_CRC8((uint8_t*)&sensor_rom[found], 7) == sensor_rom[found].crc) { found++; } } }

3. 多传感器并行读取架构

3.1 分时复用数据采集流程

为避免总线冲突,采用严格的时序控制策略:

  1. 启动所有传感器转换

    void StartAllConversions(void) { OneWire_Reset(); OneWire_WriteByte(0xCC); // SKIP_ROM OneWire_WriteByte(0x44); // CONVERT_T }
  2. 顺序读取各传感器数据

    float ReadSensorByIndex(uint8_t idx) { OneWire_Reset(); OneWire_WriteByte(0x55); // MATCH_ROM OneWire_WriteBytes(sensor_rom[idx].bytes, 8); OneWire_WriteByte(0xBE); // READ_SCRATCHPAD uint8_t data[9]; for(uint8_t i=0; i<9; i++) data[i] = OneWire_ReadByte(); return ConvertToTemperature(data); }

3.2 数据帧结构设计

推荐采用以下数据结构管理多点温度数据:

typedef struct { uint32_t timestamp; float temperatures[MAX_SENSORS]; uint8_t crc; } TemperatureFrame; void BuildTemperatureFrame(TemperatureFrame *frame) { frame->timestamp = HAL_GetTick(); for(uint8_t i=0; i<MAX_SENSORS; i++) { frame->temperatures[i] = ReadSensorByIndex(i); } frame->crc = CalculateCRC8((uint8_t*)frame, sizeof(TemperatureFrame)-1); }

3.3 总线冲突预防措施

  • 强上拉时序控制:在温度转换阶段(尤其寄生供电时)启用MOSFET强上拉

    void EnableStrongPullup(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = ONEWIRE_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(ONEWIRE_PORT, &GPIO_InitStruct); HAL_GPIO_WritePin(ONEWIRE_PORT, ONEWIRE_PIN, GPIO_PIN_SET); }
  • 重试机制:当CRC校验失败时自动重试读取

    #define MAX_RETRIES 3 float GetTemperatureWithRetry(uint8_t idx) { float temp; uint8_t retries = 0; do { temp = ReadSensorByIndex(idx); if (!isnan(temp)) break; HAL_Delay(10); } while(++retries < MAX_RETRIES); return temp; }

4. 实战代码:完整的多点测温实现

4.1 硬件初始化

void MX_DS18B20_Init(void) { // GPIO时钟使能 __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置单总线GPIO GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出 GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 发现总线上的所有传感器 DiscoverAllSensors(); }

4.2 主循环处理逻辑

void MainLoop(void) { TemperatureFrame frame; while(1) { // 启动所有传感器转换 StartAllConversions(); // 等待转换完成(12位精度需750ms) HAL_Delay(800); // 读取所有传感器数据 BuildTemperatureFrame(&frame); // 通过串口输出数据 printf("Timestamp: %lu\n", frame.timestamp); for(uint8_t i=0; i<MAX_SENSORS; i++) { printf("Sensor%d: %.2fC\n", i+1, frame.temperatures[i]); } // 间隔5秒采集一次 HAL_Delay(5000); } }

4.3 CRC校验实现

uint8_t OneWire_CRC8(const uint8_t *addr, uint8_t len) { uint8_t crc = 0; while (len--) { uint8_t inbyte = *addr++; for (uint8_t i = 8; i; i--) { uint8_t mix = (crc ^ inbyte) & 0x01; crc >>= 1; if (mix) crc ^= 0x8C; inbyte >>= 1; } } return crc; }

5. 性能优化与异常处理

5.1 时序精度提升技巧

DS18B20对时序要求极为严格,建议采用以下方法保证时序精度:

  • 使用硬件定时器:配置TIM2等基本定时器生成精确延时

    void Delay_us(uint16_t us) { __HAL_TIM_SET_COUNTER(&htim2, 0); HAL_TIM_Base_Start(&htim2); while(__HAL_TIM_GET_COUNTER(&htim2) < us); HAL_TIM_Base_Stop(&htim2); }
  • 关闭中断保护:在关键时序段禁用中断

    void OneWire_WriteByte(uint8_t byte) { uint32_t primask = __get_PRIMASK(); __disable_irq(); for(uint8_t i=0; i<8; i++) { // 严格按时序写位 } __set_PRIMASK(primask); }

5.2 常见故障排查指南

现象可能原因解决方案
检测不到任何传感器总线未正确上拉检查4.7kΩ上拉电阻连接
CRC校验频繁失败总线受干扰或时序不准缩短总线长度,优化延时函数
部分传感器数据异常ROM地址冲突重新执行ROM搜索算法
温度读数漂移寄生供电电压不足启用强上拉或改用独立供电

5.3 抗干扰设计建议

  • 总线保护:在长距离传输时添加TVS二极管(如SMAJ5.0A)
  • 屏蔽线缆:超过1米的布线建议使用屏蔽双绞线
  • 电源去耦:每个传感器VDD引脚添加100nF陶瓷电容

通过本文介绍的多点测温方案,开发者可快速构建高可靠性的分布式温度监测系统。实际项目中,建议将ROM地址信息存储在非易失性存储器中,避免每次上电重新搜索。对于超过3个传感器的场景,可通过降低采样率或采用多总线架构来保证系统稳定性。

http://www.jsqmd.com/news/1156131/

相关文章:

  • Cherry MX键帽3D模型库:从开源设计到个性化制造的完整技术指南
  • 2026年折叠箱装配式建筑行业应用选型白皮书 - 招财兔数字员工
  • 36个Cherry MX键帽3D模型:打造完美机械键盘的终极指南
  • 基于 Embedding 的智能搜索——从向量化到相似度计算的 Java 实践
  • 暗黑破坏神2存档编辑终极指南:d2s-editor完全使用教程
  • 拒绝低价克扣!昆明收的顶黄金回收对标大盘价高价结算 - 小蝶回收测评
  • AI Agent智能体实战教程:基于LangChain与LangGraph构建规划与工具调用能力
  • MCP3428与PIC18LF45K50高精度数据采集方案详解
  • 2026年7月最新合肥浪琴官方售后服务热线与网点地址查询 - 浪琴官方售后服务中心
  • Apex英雄启动运行问题全解析:反作弊、网络、性能优化解决方案
  • STM32与G6D-ASI继电器实现高效直流负载管理方案
  • Miniconda3 安装备忘:解决 conda command not found 与 shell 初始化失效
  • PyTorch nn.CrossEntropyLoss 实战:图像分割中处理类别不均衡的3种加权策略
  • 为什么选择virtCCA_driver?揭秘ARM机密计算架构的7大安全优势
  • 游戏提示CPU虚拟化未开启?从BIOS到Windows的完整解决方案
  • Ubuntu 22.04 Netplan WiFi 配置:3步完成从扫描到连接(附多AP配置模板)
  • 欧米茄清理手表污渍的妙招,有效延长手表使用寿命权威公示(2026年7月最新) - 欧米茄服务中心
  • donau-arv-gpu-extension API全解析:轻松集成GPU采集编码功能
  • 深耕 AI 全域 GEO 优化,品视传媒苗添程:精准破局企业数字获客难题 - 招财兔数字员工
  • 为什么选择openeuler/pkgs-categorizer?5大核心优势深度测评
  • Pin-Server插件通信机制:gRPC协议在编译器优化中的应用实践
  • 欧米茄官方换电池价格查询|地址和售后服务热线权威信息公告(2026年7月最新) - 欧米茄官方服务中心
  • 数字人平台能不能商用?授权、克隆、导出权限一次讲清
  • DiffSynth-Engine完全指南:从零开始构建高性能AI图像生成系统
  • openEuler Jenkins性能优化:提升门禁执行效率的10个技巧
  • 2026 广州包包回收专业门店测评,卖包走哪种渠道回款最快? - 禹竞奢收行
  • 智能体技能配置与自动化工作流搭建实战指南
  • 2026南宁回收黄金首饰金条金币 旧金断金老金三金统统高价收 - 禹竞奢收行
  • AI技能管理:从提示词复制到可复用数字资产的工程化实践
  • 终极指南:如何在Chrome浏览器中一键转换图片格式