资讯动态

单总线协议深度解析:从时序机理到DS18B20驱动实现

发布时间:2026/9/9 12:39:44 来源:尧图企业网站定制
1. 项目概述为什么单总线协议值得花时间去吃透做嵌入式开发这几年我调试过的通信协议少说也有十几种I2C、SPI、UART、CAN这些主流协议各有各的脾气。但要说哪个协议最“反直觉”、最考验程序员对时序的理解我第一个想到的就是单总线协议1-Wire。一根线既要供电又要传数据既要发命令又要收应答这套设计放到今天看依然相当精妙。单总线协议由Dallas Semiconductor现在的Maxim Integrated提出核心思想极其朴素用一根数据线完成器件识别、命令下发和数据回传。最常见的应用就是DS18B20温度传感器还有各类单总线EEPROM、单总线开关器件。你只需要一个GPIO口加一个4.7kΩ上拉电阻就能挂载多个器件这在资源受限的单片机系统里非常友好。但是——这里必须先泼一盆冷水。单总线协议最大的坑在于它的一切通信都建立在严格的时间窗口上。I2C有SCL时钟线兜底SPI有独立的时钟信号而单总线完全依靠主机主动产生精确的时序脉冲从机的应答也是通过主动拉低总线不同时长来编码的。这就导致一个问题如果你只是照葫芦画瓢抄了一段驱动代码不理解每个延时背后的物理含义一旦换个主频的单片机、换根长线、换个供电方式代码立刻失效。这篇文章我打算从物理层电气特性讲起一路讲到ROM寻址的搜索算法把单总线的完整逻辑链路拆开揉碎。不管你是刚接触DS18B20的新手还是已经在用单总线但经常被时序问题折磨的开发者我相信这篇文章都能帮你把底层逻辑彻底打通。你会明白为什么复位时序要拉低480μs为什么读时序必须在15μs内采样以及64位ROM码里的CRC校验到底在防什么。2. 物理层核心机制单线如何同时完成供电和通信2.1 开漏输出与上拉电阻一根线的秘密单总线的物理层设计可以概括为一句话所有器件通过开漏输出共享一根数据线靠一个上拉电阻维持默认高电平。开漏输出的意思是器件只能主动将总线拉低到GND而无法主动输出高电平。总线的高电平完全依赖外部上拉电阻从VCC拉上去。这个设计带来几个直接后果。第一多个器件可以同时挂在同一根线上任意器件拉低总线其它器件都能感知到电平变化不会出现两个器件同时推挽输出导致短路的问题。第二主机和从机的GPIO方向可以随时切换主机发送数据时配置为输出发送完毕后立即切回输入模式等待从机拉低总线回数据。上拉电阻的取值不是随便选的。标准推荐值是4.7kΩ但这个值是在5V供电、线长1米以内、挂载不超过8个器件的典型场景下算出来的。如果供电电压降到3.3V或者线长超过3米或者挂载器件数量增多上拉电阻就需要重新计算。上拉电阻的选型本质上是在充电速度和驱动能力之间找平衡。电阻越小总线从低电平恢复到高电平的速度越快但同时灌入从机的电流越大从机拉低总线时承受的灌电流也越大。DS18B20等器件的数据手册通常会给出一个IOL低电平灌电流上限比如4mA。当总线被拉低时流过上拉电阻的电流就是VCC/R_pullup。5V供电、4.7kΩ电阻时电流约为1.06mA远低于4mA安全。但如果把电阻改成1kΩ电流就变成5mA已经超出器件规格长期运行可能损坏从机。我之前做过一个项目线缆长度接近5米4.7kΩ上拉电阻在高速模式下根本无法正常工作波形上升沿明显变缓读回来的数据偶发错误。后来把电阻降到2.2kΩ才稳定。如果你的项目线缆长或者干扰大在保证灌电流不超标的前提下可以适当减小上拉电阻这算是单总线调优的一个实用技巧。2.2 寄生供电两根线解决供电和数据单总线的另一个精妙设计是寄生供电。DS18B20这类器件只有两个引脚DQ和GND它不单独接VCC而是从数据线上“偷电”。数据线为高电平时内部电容充电存储能量数据线被拉低时靠电容放电维持芯片工作。这个设计在分布式测温场景下非常实用。你只需要两根线数据线和地线就能串联挂载几十个温度传感器省去了布电源线的成本。但寄生供电有几个必须注意的坑。第一个坑是转换精度问题。DS18B20进行温度转换时需要的电流峰值可达1.5mA如果此时数据线长时间处于低电平内部电容电量耗尽转换就会失败结果读到0xFFFF之类的异常值。所以在发起温度转换命令0x44后主机必须在转换期间典型750ms强拉高总线也就是把GPIO配置为推挽输出高电平给器件“强制充电”。很多人在寄生供电模式下读不到正确温度就是这个细节没处理。第二个坑是强上拉的时限。强拉高电平只应在温度转换期间使用其它时候必须回到弱上拉。因为如果一直强拉从机就无法通过拉低总线来发送应答和数据了。控制好“什么时候强拉、什么时候释放”是寄生供电模式的核心。我个人的习惯是除非板级空间极度受限否则尽量用外部供电模式。DS18B20的三个引脚都在同一侧VCC和DQ挨得很近外部供电只需多走一根线却能免去强上拉时序的麻烦。只有在需要远距离多节点测温、布线成本敏感的工业场景下寄生供电才真正值得使用。2.3 时序基础为什么单总线对延时这么敏感单总线的时隙Time Slot机制是所有通信的基础。主机通过控制总线拉低的时间长度来发送“0”和“1”通过采样时刻来判断从机返回的是“0”还是“1”。整个通信过程可以被看作是一系列标准化的“脉冲对话”。以标准12μs速率为例几个关键时间窗口如下复位脉冲主机拉低480μs以上然后释放等待从机应答存在脉冲从机在主机释放后60~240μs内拉低60~240μs表示“我在”写0时隙主机拉低60~120μs写1时隙主机拉低1~15μs然后释放读时隙主机拉低1~15μs然后释放在释放后的15μs内采样总线从这些参数就能看出来单总线的时序容差相当紧。尤其是读时隙从机在检测到主机释放总线后会在很短时间内决定是否拉低总线。如果主机采样太晚可能从机已经释放总线了读到的就是高电平“1”导致“0”被误判为“1”。这里有一个普通文档不会告诉你的经验读时序的延时参数和单片机主频的关系。我见过很多人用NOP指令数延时而不是用定时器结果换了个高主频的单片机NOP次数没改整个时序就乱了。正确做法是写一个基于微秒μs的通用延时函数不管是软件延时还是定时器延时先校准再通信。DS18B20这类器件还算宽容但如果你用的是高速单总线器件时序窗口更窄延时不精确会直接导致通信失败。3. ROM寻址机制一码识别所有从机3.1 64位ROM码结构拆解单总线支持一主多从总线上可以挂载多个器件。主机怎么区分它们答案是每个器件出厂时固化的64位ROM码。这个码是全球唯一的相当于器件的“身份证号”。64位ROM码分三部分。最低8位是家族码Family CodeDS18B20的家族码是0x28DS2431 EEPROM是0x2D。接下来48位是器件序列号同一型号的不同器件靠序列号区分。最高8位是前56位的CRC8校验值用于检测主机是否读错了ROM码。这个CRC8对整个系统非常重要。单总线通信没有独立的错误反馈通道主机读到的数据是否正确完全靠CRC来验证。CRC8的生成多项式是x^8 x^5 x^4 1也就是0x8C反转后为0x31。每读取完64位ROM码主机会重新计算前56位的CRC和最后8位比对。如果一致说明ROM码读取无误如果不一致说明通信被干扰或者器件异常。我在实际调测中经常遇到这种情况总线接触不良或者线缆过长读回来的ROM码中间某一位翻转。如果没有CRC校验主机会把错误的器件当成正常的从机来处理导致采集通道错误。有了CRC校验主机至少能知道这次读取失败了然后选择重试。这种容错机制在环境恶劣的工业现场尤为关键。CRC的计算有两种方式。一是查表法适合资源充足的平台速度快二是逐位计算法适合单片机这种资源紧张的场景代码简单但耗时。我列出逐位计算的C代码实现uint8_t calc_crc8(uint8_t *data, uint8_t len) { uint8_t crc 0; for (uint8_t i 0; i len; i) { crc ^ data[i]; for (uint8_t j 0; j 8; j) { if (crc 0x01) { crc (crc 1) ^ 0x8C; } else { crc 1; } } } return crc; }这个算法在每一个单总线项目中几乎都会用到。需要注意的是多项式0x8C是直接计算版本和0x31是位序反转的关系先用哪种都行只要保证和器件内部的CRC算法匹配。DS18B20系列是LSB先传所以直接计算版本用0x8C是对的。3.2 单总线搜索算法逐个找出总线上的设备当总线上挂载多个器件时主机要找出所有器件的ROM码这就要用到单总线搜索算法。这个算法本质上是一个二叉树遍历每次通过两个读时隙读取一位ROM码的“值”和“补码”从而确定该位是0、是1还是冲突位。搜索算法的核心逻辑是这样的主机先发ROM搜索命令0xF0然后对ROM码的每一个位执行两次读时隙。第一次读时隙读取该位的真实值第二次读时隙读取该位的反码。如果两次读到的结果相同说明总线上所有未匹配的器件在这一位上的值一致。如果两次读到的结果不同说明这一位存在冲突既有人是0也有人是1。主机根据冲突记录来决定下一步走向先走一条路径记录其它冲突位的位置回头再走另一条路径。我梳理一下搜索流程的关键步骤发送复位脉冲等待所有从机应答发送0xF0搜索命令对第0位到第63位依次执行两个读时隙获取值位和补码位如果值位和补码位相同且都是0说明该位在所有未匹配器件中都是0继续记录如果值位和补码位相同且都是1说明没有器件应答搜索失败如果值位和补码位不同说明存在冲突需要根据冲突位决策表决定当前路径走向每确定一位向总线写入该位的值让不匹配的器件自动退出完成64位后得到一个完整的ROM码然后从头开始重新搜索下一条路径这段逻辑听起来简单实际写代码时容易在“回溯”环节出错。核心难点在于当碰到冲突位时你选择了其中一个分支但下次搜索时必须回到最近的一个未曾探索的分支而不是从头再来。我常用的做法是用一个方向标记数组来记录每一位最后一次搜索时的走向每次搜索结束后从最后一位往前回溯找到最近的一个“方向为0且存在冲突”的位改成1再继续。搜索算法的时间复杂度是O(n^2)每个器件需要做64次读时隙和64次写时隙。挂载8个器件时完整扫描一遍的总线时间非常可观。如果应用中器件是固定不变的更推荐的做法是上电时做一次完整搜索把ROM码列表存起来之后通过匹配ROM命令0x55直接访问指定器件。3.3 三条核心ROM指令跳过、匹配、搜索单总线协议体系中有几条关键的ROM指令理解它们的区别是正确操作总线的前提。跳过ROM命令0xCC是最简单也最常用的指令。它不需要提供任何ROM码直接跳过器件识别环节后续访问的是总线上所有器件。注意“所有”这个词——如果总线上挂了多个器件使用0xCC后所有器件同时响应后续的数据命令冲突无可避免。所以0xCC只能应用于单点挂载场景。匹配ROM命令0x55需要主机在指令之后依次发送64位ROM码总线上只有ROM码匹配的那个器件会响应后续命令其它器件全部进入休眠等待。这是多设备场景下访问指定器件的最常用方式。搜索ROM命令0xF0刚才已经详细说过它不指定目标器件而是让所有器件参与应答主机通过冲突位机制逐个识别出每个器件的ROM码。除了这三条还有两条报警搜索命令0xEC和条件搜索命令用于筛选特定状态的器件。典型场景是DS18B20的温度报警功能器件设置了TH和TL阈值当温度超限后进入报警状态主机用0xEC命令可以快速搜索出所有处于报警状态的器件不需要逐个读取温度。这个功能在CPU散热监控、冷链运输等场景中非常实用可以显著降低巡检时间。这里有一个我踩过的坑使用0xCC后如果总线上有两个器件同时响应从机返回的数据是两个器件的数据“线与”结果。两个器件同时拉低总线读到的就是0同时释放读到的就是1一个拉低一个释放读到的还是0。最终读到的是逻辑与后的结果既不是A的数据也不是B的数据。排查这个问题的线索是读取到的数据和CRC校验总是不通过而且每次都不同。4. 实操过程从零手写单总线驱动4.1 驱动框架设计与时序函数实现纸上谈兵再多不如直接动手写代码。我从一个典型的单片机项目出发展示如何从零搭建一套完整的单总线驱动。假设平台是常见的STM32系列开发环境使用标准外设库或HAL库均可核心是GPIO的方向控制和电平读写。首先要实现三个底层函数拉低总线、释放总线切回输入模式、读取总线电平。这里的关键是GPIO模式的切换。在开漏模式下如果GPIO配置为开漏输出写1就是释放总线因为开漏输出的高电平靠外部上拉实现写0就是拉低总线。这是最简洁的做法。#define ONE_WIRE_PORT GPIOB #define ONE_WIRE_PIN GPIO_PIN_0 // 开漏输出模式下写1 释放总线写0 拉低总线 static void ow_write_bit(uint8_t bit) { if (bit) { HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(ONE_WIRE_PORT, ONE_WIRE_PIN, GPIO_PIN_RESET); } }但更推荐的做法是在推挽输出和输入模式之间切换。原因是推挽输出的响应速度更快尤其在线缆较长、负载电容较大的场景下推挽模式能提供更强的驱动能力。代价是需要额外配置GPIO模式且必须保证切换过程中不产生毛刺。static void ow_set_output(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; GPIO_InitStruct.Pin ONE_WIRE_PIN; GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(ONE_WIRE_PORT, GPIO_InitStruct); } static void ow_set_input(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; GPIO_InitStruct.Pin ONE_WIRE_PIN; GPIO_InitStruct.Mode GPIO_MODE_INPUT; GPIO_InitStruct.Pull GPIO_PULLUP; HAL_GPIO_Init(ONE_WIRE_PORT, GPIO_InitStruct); }有了这两个模式切换函数接下来实现复位和存在检测。复位时序是主机拉低480μs以上、释放、等待60~240μs后采样总线。如果从机存在它会在释放后的60~240μs窗口内拉低总线60~240μs。uint8_t ow_reset(void) { uint8_t presence 1; ow_set_output(); ow_write_bit(0); // 拉低总线 delay_us(500); // 复位脉冲至少480μs ow_set_input(); // 释放总线切回输入 delay_us(70); // 等待从机应答窗口60~240μs presence HAL_GPIO_ReadPin(ONE_WIRE_PORT, ONE_WIRE_PIN) GPIO_PIN_RESET ? 0 : 1; delay_us(410); // 等待存在脉冲结束 return presence; // 返回0表示有设备返回1表示无设备 }简洁起见复位成功后返回0有设备失败返回1无设备。这个约定和很多开源代码一致但我个人倾向于用更语义化的布尔值比如定义一个枚举避免代码阅读时搞混。4.2 读写时隙的代码实现读时隙和写时隙是单总线通信的最小单位。写时隙要求主机拉低总线然后根据要发送的位决定释放时间。写0需要维持拉低60μs以上写1只需要拉低1~15μs就释放。这里有一个非常容易犯的错误写完1后如果立即开始下一个时隙可能导致前一个时隙的总线释放时间不足。标准规定两个时隙之间需要至少1μs恢复时间。实际上我通常在每个时隙末尾加2~3μs的余量防止时序临界。void ow_write_bit(uint8_t bit) { ow_set_output(); ow_write_bit_internal(0); // 拉低总线 if (bit) { delay_us(8); // 写1只拉低8μs左右 ow_set_input(); // 释放总线 delay_us(65); // 补足整个时隙时间 } else { delay_us(65); // 写0保持拉低65μs以上 ow_set_input(); // 释放总线 delay_us(5); // 时隙间隔 } }读时隙的代码更讲究采样时机。主机拉低总线1~15μs后释放然后在释放后的15μs内采样。我的习惯是拉低2μs、延时6μs、采样这样能保证在窗口内稳定读到电平。uint8_t ow_read_bit(void) { uint8_t bit; ow_set_output(); ow_write_bit_internal(0); // 拉低总线 delay_us(2); // 保持拉低2μs ow_set_input(); // 释放总线 delay_us(6); // 等待从机响应必须在15μs内采样 bit HAL_GPIO_ReadPin(ONE_WIRE_PORT, ONE_WIRE_PIN); delay_us(50); // 等待时隙结束 return bit ? 1 : 0; }整套驱动写完之后我建议先用逻辑分析仪或者示波器抓一次波形重点检查三件事复位时序的宽度是否在480μs左右、写0和写1的波形是否有明显区别、读时隙的采样点是否在窗口内。用示波器校准一次时序比低效调试快得多。4.3 寄生供电模式下的特殊处理强上拉实现在寄生供电模式下温度转换期间需要强上拉。实现方式有两种。一是使用MOSFET开关电路由MCU的另一个GPIO控制在转换期间将数据线直接连接到VCC二是直接将MCU的GPIO配置为推挽输出高电平由MCU提供强上拉能力。后者在低功耗和低成本场景下更常见。简单说一下第二种方式的代码逻辑// 发起温度转换命令0x44 ow_reset(); ow_write_byte(0xCC); // 跳过ROM假设单设备 ow_write_byte(0x44); // 启动温度转换 // 进入强上拉模式 ow_set_output(); ow_write_bit_internal(1); // 推挽输出高电平持续供电 delay_ms(750); // 等待转换完成12位精度典型需要750ms // 退出强上拉恢复弱上拉 ow_set_input();这段代码看起来简单但有个隐藏的性能短板750ms的延时是阻塞式延时整个MCU被卡住。如果系统里同时有传感器采集、通信上报、用户交互等多个任务这种写法会导致系统完全假死。更专业的做法是发起转换后立即退出强上拉然后调度器切换去做其它任务用一个定时器记录时间到点后再回来读取温度。这样既利用了转换时间又不阻塞系统。4.4 温度读取完整流程一个可复现的DS18B20示例把前面所有环节串起来一个完整的DS18B20温度读取流程如下复位总线检测器件存在发送跳过ROM命令0xCC单点场景发送温度转换命令0x44等待转换完成外部供电模式下可以延时或者读取忙标志复位总线发送跳过ROM命令0xCC发送读取暂存器命令0xBE连续读取9个字节温度为前2个字节后面是告警阈值和CRC计算CRC校验数据有效性解析前2个字节得到温度值温度数据的解析规则是最低位代表0.0625°C即1/16°C数据是12位有符号数用左对齐方式存储。负数时需要进行符号扩展处理后取补码。int16_t parse_temperature(uint8_t lsb, uint8_t msb) { int16_t raw (msb 8) | lsb; if (raw 0x8000) { raw (raw 0x7FFF) - 0x8000; // 处理负数 } return (int16_t)(raw * 625 / 10000); // 保留两位小数精度 }这里乘625除10000是为了保留小数点后两位的同时避免浮点运算。如果你的平台支持浮点直接乘以0.0625更直观但在单片机里浮点开销较大能避免就避免。单总线驱动看似简单实际调试中各种奇怪问题层出不穷。下面我整理了一份我自己踩坑记录形成的问题排查表基本覆盖了单总线开发中的绝大多数疑难杂症。5. 常见问题与排查技巧实录5.1 通信完全失败的排查路径单总线通信完全无响应是最常见的故障现象。我推荐的排查顺序是先查硬件再查时序最后查逻辑。硬件层面先用万用表测量数据线对地电压。正常情况下静态时总线应该被上拉到VCC读到的电压接近电源电压。如果总线电压只有零点几伏说明有器件损坏或接线短路。接着检查上拉电阻的焊点是否虚焊尤其是使用洞洞板或手工焊接时上拉电阻脱落导致的故障非常隐蔽。时序层面用示波器抓复位波形。重点看主机拉低的脉冲宽度是否在480μs以上。有些代码在时序延时上偷工减料只拉了200μs就释放导致从机根本没有识别到复位信号。逻辑层面确认发送每条指令前是否都执行了正确的复位操作。单总线协议规定每一次完整的命令交互都以复位开始。如果上一条指令结束后没有复位就发下一条指令从机的状态机可能还停留在上一次通信的中途导致后续命令全部无效。5.2 数据偶发错误CRC校验失败的典型原因CRC校验失败是“器件能找到但数据不可靠”的典型表现。我在项目里遇到过几种情况。线缆过长导致信号完整性下降是最常见的原因。5米以上的普通杜邦线在高速模式下的寄生电容会显著拉慢上升沿。此时可以尝试减小上拉电阻到2.2kΩ或2.7kΩ降低通信速率改造成Overdrive模式需要在器件支持的前提下操作标准速率下则优化时序余量或者在线缆末端加一个0.1μF的滤波电容。供电不稳定是另一个容易被忽略的因素。如果DS18B20的VCC纹波过大ADC转换结果会出现随机偏差导致读回的温度值跳动甚至CRC错误。解决办法是在VCC和GND之间加100nF去耦电容并且尽量靠近器件引脚放置。还有一种情况是代码层面的读时序的采样点太晚。从机返回0后它只维持拉低一定时间就释放了如果主机等到释放后才采样读到的就是1。这种错误是位级的CRC很容易发现但定位却需要逐位对比比较耗时。用逻辑分析仪一次就能看清。5.3 多设备挂载时的地址冲突与扫描失败多设备场景下最常见的问题是搜索算法扫不全设备。第一次扫描能发现3个设备第二次只有2个循环几次数量不稳定。这个问题几乎都是搜索算法的回溯逻辑有缺陷。排查思路是打印每个ROM码的搜索路径。如果两次扫描得到的同一器件ROM码完全相同说明回溯逻辑基本正确如果同一个器件两次扫到的ROM码不一致说明写入每一位时出现了时序问题大概率是写时隙的延时不足。另一个坑是总线上有器件在搜索过程中掉线。单总线器件不是热插拔友好的如果在搜索过程中拔掉某个器件总线电平会出现未定义状态导致整个搜索流程崩溃。工业现场如果需要支持热插拔建议在软件层增加总线状态检测和自动重搜索机制检测到设备数量变化时自动重新扫描。5.4 单总线通信的电气特性限制对照表现象可能原因解决方案总线无应答上拉电阻缺失或损坏检查R_pullup焊接测量静态电平总线无应答主机GPIO方向配置错误确认输出/输入模式切换正常数据偶发错误线缆过长上升沿变缓减小上拉电阻或者增加总线驱动芯片数据偶发错误供电纹波过大加100nF去耦电容温度值跳动很大传感器引脚接触不良重新焊接采用压接端子搜索设备数量不稳定搜索算法回溯逻辑缺陷检查冲突位处理代码寄生供电模式下读取失败转换期间未强上拉转换命令后必须强拉高电平Overdrive模式无法通信器件不支持高速模式检查器件型号确认是否支持Overdrive这张表虽然无法覆盖所有问题但绝大多数常见故障都能在这里找到思路。如果你遇到的问题不在表中我的建议是先抓波形再怀疑代码。单总线的时序全部可以通过示波器观察物理层的异常用万用表也能快速定位不要陷入盲目改代码的循环。6. 单总线与其它总线协议的对比和选型建议6.1 对比I2C、SPI、UART各自的适用边界单总线协议在嵌入式通信协议家族中的地位挺特殊的。它牺牲了速度、放弃了时钟线的确定性换来的是极简的硬件连接。到底什么时候用单总线什么时候该选I2C或SPI我在项目选型时有一套自己的判断标准。I2C同样支持一主多从、同样有寻址机制但它是两线制SCLSDA通信速率在标准模式下100kHz快速模式下400kHz比单总线快得多。I2C使用7位或10位地址寻址地址冲突需要硬件跳线解决。如果你的系统里有两三个传感器需要挂在一组总线上I2C通常比单总线更合适。I2C的时钟线意味着从机不需要精确的时间窗匹配时序容差比单总线大很多。SPI是四线制SCLK、MOSI、MISO、CS速度可以到几十MHz是全双工通信。它需要每个从机一个片选信号当从机数量多时占用的GPIO也很多。SPI适合大数据量、高速率、从机数量较少的场景比如Flash芯片、TFT屏幕、SD卡这类外设。UART适合点到点通信虽然也能通过RS-485组网但需要额外的收发控制逻辑。单总线的一个独特优势是它只需要一根数据线寄生供电模式下只用两根线这在穿越旋转关节、狭窄管道或者简化接线时非常值钱。维度单总线1-WireI2CSPIUART最少信号线1寄生供电24不含片选2通信速率15.4kbps标准100k~400kbps最高数十Mbps可配置寻址方式64位ROM码搜索7位/10位地址片选信号无地址时序复杂度高中低低多从机能力强可多挂强可多挂有限靠片选弱需RS-485典型应用DS18B20、EEPROM温湿度、加速度计Flash、屏幕蓝牙模块、GPS6.2 单总线的不可替代场景单总线协议有一个其它协议无法替代的优势单根线的远程组网能力。在一些测量点分散且距离较远、但数据量很小的场景中比如粮仓温度监测、机房温度巡检、养殖场环境监测单总线几乎是最优解。我参与过的一个项目是冷库多点测温需要在冷库内布置30个DS18B20传感器传感器沿一根长约20米的数据总线分布。备选方案只有两个单总线或者每个传感器独立接UART线。如果用UART需要30对线布线成本和故障概率急剧上升。单总线方案只需要一对线串联所有器件一个GPIO就搞定了全部数据采集。另一个不可替代的场景是单总线EEPROM的“钥匙扣”应用。DS2432等器件内置SHA-256加密引擎可以用于设备认证。它的独特之处在于只需一个接触式金属触点就能完成供电和通信非常适合认证接触点场景。这种物理层面的极简性是I2C和SPI无法比拟的。6.3 选型时容易被忽略的四个细节第一单总线的带宽是共享的。即使是标准速率一次完整的温度转换加数据读取也要花费上百毫秒。如果总线上挂了30个器件且都需要长期高速轮询单总线的响应速度会成为一个瓶颈。这种情况下建议改用RS-485总线或者无线方案。第二单总线的搜索算法对主控CPU造成不小的负担。每搜索一个器件需要几百次GPIO操作和精确延时如果主控是Cortex-M0级别的低端MCU完整搜索一次几十个器件可能会耗时几十毫秒。如果设备又需要频繁刷新CPU占用率会相当高。第三单总线的时序与温度相关。器件在极端温度下比如零下40°C工业环境内部RC振荡器的频率会发生偏移影响时隙稳定性。工业级单总线产品虽然经过温度补偿但通信时序的余量会变小。在极端温度下设计时应尽量让主机的时序参数落在标准范围的正中间避免贴着极限值。第四单总线的器件地址类型不同。有些器件如DS2401是只读ROM有些器件如DS2431允许用户写入EEPROM。选型前务必确认所需的存储能力和地址管理方式避免项目中期发现存储不足而重新选型。7. 根据个人经验延伸几个提高可靠性的做法最后分享几个我在实际项目中反复验证过的细节这些内容在标准数据手册里往往不会写但对提高单总线系统的长期稳定性很有帮助。第一加总线保护电阻。在MCU的GPIO和数据线之间串联一个100Ω到220Ω的电阻可以抑制热插拔时的浪涌电流还能在高电压误接时保护MCU引脚。这个电阻不影响正常通信但关键时刻能救命。第二留意ESD防护。户外或者工业设备中数据线经过长距离布线后会耦合大量静电和感应雷浪涌。在传感器侧和主机侧各加一个TVS管比如SMBJ5.0A可以有效抑制过压损坏这是产品可靠性设计的基本功。第三电源去耦不能省。无论是DS18B20还是其它单总线器件在VCC和GND之间加100nF的去耦电容能让芯片供电更稳定ADC转换结果更可靠。很多“温度偶然跳动一下”的诡异问题加个电容就解决了。第四软件层面做数据滤波和重试机制。不要认为单片机读到的数据一定是真实的物理值要在应用层做合理性判断。比如我习惯在读取后判断CRC、检查温度范围若连续3次读到异常值则判定传感器故障并报警。这套机制增大了代码量但换来了现场维护人员的大量时间。第五充分利用单总线器件的报警命令。与其全局轮询每个器件的温度是否超限不如利用报警搜索命令0xEC快速找到超限器件。尤其在机柜监控、冷库等场景中报警搜索可以显著降低巡检时间把宝贵的MCU时间留给其它任务。单总线协议看起来很“古董”但它在一根线的物理约束下做到了器件识别、寻址访问、数据校验、供电通信一体化的设计这种兼顾简洁和可靠性的思路值得每个嵌入式开发者在动手写代码之前好好品一品。如果你能完全理解复位时序、时隙机制、ROM搜索算法这三座大山单总线协议就不再是总是出bug的黑盒子而是真正掌握在手中的工具。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价