第6章:通信接口的硬件特性——为什么你的UART乱码、I2C死锁、SPI干扰大?

大家好,我是老张。上一章咱们把电源设计聊透了,板子供电稳了,MCU也跑起来了。接下来该让芯片和芯片之间"说话"(通信)了。

很多做嵌入式软件的兄弟觉得,通信嘛,不就是TX接RX、SCL接SCL,线连上代码写对就行了。可真到调试的时候,串口偶尔乱几个字节、I2C跑着跑着就挂死、SPI一上高速数据就出错、CAN总线换个终端电阻就不行......这些问题你如果只会从软件里调时序、加延时,能把你调到怀疑人生。

因为这些问题的根,一大半不在代码,在物理层 ------在电平、在走线、在终端电阻、在总线拓扑。这一章老张就带你逐一拆解四种最常用的嵌入式通信接口:UART、I2C、SPI、CAN,把它们的硬件特性和常见坑一次性说清楚。

目录

一、UART------最老牌的串口,坑一点不少

[1.1 UART的硬件本质](#1.1 UART的硬件本质)

[1.2 TTL串口、RS232、RS485------别混了](#1.2 TTL串口、RS232、RS485——别混了)

[1.3 波特率误差与采样时钟------时钟不准,通信必乱](#1.3 波特率误差与采样时钟——时钟不准,通信必乱)

[1.4 长线传输的振铃与反射](#1.4 长线传输的振铃与反射)

二、I2C------两根线打天下,但时序是硬伤

[2.1 I2C的硬件拓扑](#2.1 I2C的硬件拓扑)

[2.2 上拉电阻的选择------不是随便一个电阻就能用](#2.2 上拉电阻的选择——不是随便一个电阻就能用)

[2.3 I2C的死锁问题------总线挂死了怎么办?](#2.3 I2C的死锁问题——总线挂死了怎么办?)

[2.4 电平转换与总线隔离](#2.4 电平转换与总线隔离)

三、SPI------高速是优势,高速也是麻烦

[3.1 SPI的硬件拓扑](#3.1 SPI的硬件拓扑)

[3.2 信号完整性问题------SPI不是线连上就能跑](#3.2 信号完整性问题——SPI不是线连上就能跑)

[3.3 多从设备的管理------CS引脚的坑](#3.3 多从设备的管理——CS引脚的坑)

[3.4 长线SPI怎么办?](#3.4 长线SPI怎么办?)

四、CAN总线------工业通信的扛把子

[4.1 CAN的硬件本质](#4.1 CAN的硬件本质)

[4.2 终端电阻------没有它总线就废了](#4.2 终端电阻——没有它总线就废了)

[4.3 总线拓扑与走线](#4.3 总线拓扑与走线)

[4.4 共模电压范围与隔离](#4.4 共模电压范围与隔离)

五、四种接口硬核对比

六、本章总结


一、UART------最老牌的串口,坑一点不少

1.1 UART的硬件本质

UART(通用异步收发传输器)是嵌入式世界最简单、最古老的通信方式。两根线:TX(发送)接对方RX(接收),RX接对方TX,再加一根地线。异步通信,没有时钟线,双方约定好波特率,各自按自己的时钟采样。

硬件上的关键点就两个:电平标准信号质量

1.2 TTL串口、RS232、RS485------别混了

这是新手最容易搞混的概念。UART是协议 ,TTL/RS232/RS485是物理层标准,决定信号用什么样的电压来表示0和1。

TTL串口:就是MCU引脚直接出来的3.3V或5V逻辑电平。高电平是逻辑1,低电平是逻辑0。传输距离一般不超过一两米,板间通信够用。直接怼就行,成本为零。

RS232 :把TTL电平转换成±12V左右的差分信号(对地),逻辑1是-3V到-15V,逻辑0是+3V到+15V。为什么搞这么高电压?为了抗干扰和长距离,最远能传15米左右。老式电脑后面的DB9串口就是RS232。嵌入式里想用RS232,加一颗MAX3232之类的电平转换芯片就行,注意外围电容值按芯片手册配,配错通信会出错。

RS485 :工业上用得最多。它是差分信号,两根线A和B,A比B高0.2V以上是逻辑1,B比A高0.2V以上是逻辑0。因为是差分信号,对共模干扰天然免疫,传输距离能到千米级别,还能在一对线上挂多个设备(多点通信)。嵌入式里加一颗MAX485/SP3485芯片就能用。

翻车点:有兄弟直接用MCU的TTL串口拉出5米长线去通信,结果数据乱飞。TTL是单端信号,对地参考,长线上感应的共模噪声直接叠加在信号上,根本没抵抗力。长距离通信请自觉上RS485或者RS232,别用TTL硬扛。

1.3 波特率误差与采样时钟------时钟不准,通信必乱

UART接收端用自己的时钟去采样数据线,如果收发双方的时钟偏差太大,采样点就会逐渐漂移,最终采错位。

大多数MCU的UART用16倍过采样,即在每个数据位的中间位置采样。整帧的采样容差大约是±5%左右。所以双方波特率偏差不能太大。

两个常见坑

  • 内部RC振荡器跑串口:内部RC精度只有1%左右,常温还勉强,温度一变就可能偏到3%以上,两个设备一个偏正一个偏负,加起来就超过5%了,通信必出错。工业产品跑串口,老老实实上外部晶振。

  • 非标准波特率:有些特殊外设要求非标波特率,但你的MCU的UART分频器可能产生不了准确值,实际波特率偏差过大。设计前先算一下分频误差,超过2%就要小心。

1.4 长线传输的振铃与反射

TTL信号在长线上传输,如果线缆特性阻抗不匹配,信号会在端点反射,产生"振铃"------在信号边沿后面跟着一串衰减的振荡。这个振荡如果幅度够大,可能被接收端误判为额外的数据脉冲。

解决办法:在信号线始端或终端串一个几十Ω的小电阻(比如22Ω~100Ω)吸收反射能量,或者在接收端对地并一个小电容滤除毛刺。当然最好的办法还是:别用TTL跑长线,换RS485。

二、I2C------两根线打天下,但时序是硬伤

2.1 I2C的硬件拓扑

I2C是飞利浦搞出来的双线串行总线:SCL(时钟)和SDA(数据),两条线都通过上拉电阻拉到VDD,所有设备开漏输出接在上面,谁都可以拉低,但谁都不能主动拉高,释放后靠上拉电阻恢复高电平。

这根总线可以挂多个主设备和多个从设备,每个从设备有唯一的7位或10位地址。

2.2 上拉电阻的选择------不是随便一个电阻就能用

上一章提过一嘴,这里展开说透。I2C的上拉阻值直接决定了通信的可靠性和速度。

阻值太小:总线拉低时,上拉电阻会流过电流 VDD/R。3.3V/1kΩ=3.3mA,单个器件可能承受得住,但如果总线上有多个器件同时拉低,或者器件驱动能力弱,低电平就拉不实。低电平不够低(比如高于0.4V),接收端可能认不到逻辑0。

阻值太大:总线释放后,上拉电阻给总线寄生电容充电,上升沿会变缓。I2C规范要求上升时间在标准模式(100kHz)小于1000ns,快速模式(400kHz)小于300ns。用10kΩ上拉,总线电容100pF,RC时间常数1μs,上升沿超标,数据采样会出错。

实战选值:我用得最多的是3.3kΩ~4.7kΩ。100kHz随便跑,400kHz也从容。总线上设备多、线缆长、寄生电容大时,选小一点;追求低功耗时,选大一点降速用。

另外,上升沿太慢还会导致从机误触发。如果上升沿慢吞吞地爬过逻辑门限区域,线上的一点小干扰就可能产生一个毛刺,从机会把这个毛刺当成额外的时钟脉冲,导致状态机错乱,总线死锁。

2.3 I2C的死锁问题------总线挂死了怎么办?

I2C有一个经典故障:主设备正在读数据,突然一个干扰或复位,导致从设备还在等着输出下一个数据位,死死地把SDA拉低不释放,主设备想发停止条件却发现SDA一直被从设备拉着,总线彻底卡死。

解决方法:软件上,主设备检测到SDA被长时间拉低,可以手动翻转SCL,产生额外的时钟脉冲,让从设备把剩下的数据位"吐完",释放SDA。硬件上,在SDA和SCL上各对地并一个几pF到十几pF的小电容,可以吸收毛刺减少误触发。

还有一种死锁场景:上电时序问题。如果MCU上电速度比外设快,MCU已经在操作I2C了,外设还没初始化完,外设可能会把SDA拉住。可以在MCU启动代码里加一段延时,等外设准备好。

2.4 电平转换与总线隔离

3.3V主控挂5V外设,或者3.3V主控挂1.8V传感器,就需要电平转换。I2C电平转换最经典的方案是老张在第3章讲过的双MOS管方案(两个N沟道MOS管加四个上拉电阻),成本几毛钱,双向自动转换,稳定可靠。

长距离I2C(比如超过一米)是作死行为。如果一定要远距离,上I2C缓冲器/延长器芯片(如PCA9515、P82B715),或者干脆换CAN/RS485。

三、SPI------高速是优势,高速也是麻烦

3.1 SPI的硬件拓扑

SPI是四线全双工总线:SCK(时钟)、MOSI(主出从入)、MISO(主入从出)、CS(片选)。主设备产生时钟,从设备响应。速度轻松上10MHz,快的能到50MHz以上。

硬件上看着简单,但高速就带来了高速的麻烦。

3.2 信号完整性问题------SPI不是线连上就能跑

SPI跑低速(几MHz以下),杜邦线随便飞都没问题。一上10MHz,信号质量问题全冒出来了。

时钟反射与振铃:SCK是高频方波,如果走线长且没有阻抗匹配,信号边沿会产生严重的振铃。从设备可能把一个振铃的毛刺当成额外的时钟沿,数据就被多移了一位,全乱套。

数据与时钟的偏移:MOSI和MISO的数据需要在SCK的采样沿之前稳定下来。高速时如果数据线走线比时钟线长太多,或者经过的过孔数不一样,数据到达的时间就会偏移,导致建立/保持时间不够,采样出错。做高速SPI的PCB,SCK、MOSI、MISO三根线最好做等长处理,走线差距控制在几十mil内。

串扰:SPI几根线并排走,一根线上的高速跳变会通过寄生电容耦合到旁边的线上。如果CS线被SCK串扰干扰,可能产生假动作,从设备莫名其妙被选中或释放。高速SPI走线时,线间距尽量拉大(至少2倍线宽),中间用地线隔离更好。

3.3 多从设备的管理------CS引脚的坑

SPI挂多个从设备,主控用不同的CS片选引脚来选中对应的从设备。看似简单,但有两个坑:

  • CS悬空:未被选中的从设备的CS引脚必须被拉到确定的高电平。如果悬空,干扰会让它随机被选中,跟正在通信的那个从设备在MISO上打架。给每个CS脚加一个10kΩ上拉电阻,选中时拉低,不选时上拉保持高,简单可靠。

  • MISO冲突:多个从设备的MISO都连在一起接主设备的MISO。如果两个从设备同时被选中(比如CS线被干扰),它们会同时在MISO上驱动输出,造成总线冲突,严重时烧IO口。所以CS的上拉和去干扰非常重要。

3.4 长线SPI怎么办?

SPI设计上就是板内通信,不适合拉长线。如果必须拉远(比如半米以上),几个保命招:

  • 降速,降到1MHz以下甚至几百kHz。

  • 串阻尼电阻,在SCK和MOSI/MISO的源端各串一个22Ω~100Ω的小电阻,吸收反射。

  • 用差分转换芯片,把SPI信号转成LVDS差分信号传输,接收端再转回来。比如用SN65LVDS系列。

四、CAN总线------工业通信的扛把子

4.1 CAN的硬件本质

CAN(控制器局域网)是博世搞的差分总线,专为恶劣环境设计。两根线CAN_H和CAN_L,隐性电平(逻辑1)时两根线电压都在2.5V左右,差分电压接近0V;显性电平(逻辑0)时CAN_H约3.5V、CAN_L约1.5V,差分电压约2V。

因为是差分信号,对共模干扰天生免疫;因为用差分电压判0/1而不是绝对电压,抗干扰能力极强。嵌入式里加一颗CAN收发器(如TJA1050、SN65HVD230)就能用。

4.2 终端电阻------没有它总线就废了

CAN总线的两端必须各接一个120Ω的终端电阻,并联后总线等效阻抗60Ω。这个终端电阻的作用是吸收信号反射

CAN信号在总线上是以电磁波形式传播的,传到总线端点时如果没有匹配的负载,信号会反射回来,跟正常信号叠加,造成振铃和误码。120Ω刚好匹配双绞线电缆的特性阻抗。

翻车实录:有次我调两块CAN通信,偶尔能通偶尔不通,数据错误率奇高。查代码查半天,最后发现是只焊了一端的终端电阻,忘记另一端也要焊。补上后瞬间稳定。CAN总线一定要两端各120Ω,缺一不可。

4.3 总线拓扑与走线

CAN要求总线拓扑是直线型,一根主线从头到尾,设备通过短支线挂在主线上。支线越短越好,一般不超过30cm(高速CAN)。不要搞成星型或者树形,各种反射叠加起来信号质量一塌糊涂。

线缆用双绞线,CAN_H和CAN_L绞在一起,共模干扰同时在两根线上感应相同的电压,差分接收时自动抵消。不要两根线分开走,共模抑制效果大打折扣。

4.4 共模电压范围与隔离

CAN节点之间的地电位可能相差几十伏(工业现场),所以CAN收发器有较宽的共模输入电压范围(如-7V到+12V)。如果地电位差可能更大,或者需要保护MCU,就要加隔离CAN方案:在MCU和CAN收发器之间加数字隔离器,收发器侧用隔离电源供电。

隔离CAN芯片如ISO1050、ADM3053,内部集成了隔离和收发器,用起来跟普通CAN一样,成本高一些,工业产品必备。

五、四种接口硬核对比

接口 线数 速度 距离 拓扑 电平 最大坑
UART 2+地 几十k~几Mbps 米级(TTL)~千米(RS485) 点对点(可多点485) TTL/RS232/RS485 波特率误差、长线振铃
I2C 2 100k/400k/1Mbps 板内,最长1-2米 多主多从总线 开漏+上拉 上拉阻值、死锁、上升沿慢
SPI 4+片选 几M~50Mbps 板内,最长几十cm 一主多从星形 推挽 高速信号完整性、CS悬空
CAN 2 最高1Mbps 几十米到几千米 直线型总线 差分 终端电阻缺失、拓扑错误

六、本章总结

这一章老张把嵌入式最常用的四种通信接口的硬件特性过了一遍。记住几个核心要点:

  • UART:电平标准要分清(TTL/RS232/RS485),长距离别用TTL硬扛,波特率误差要从时钟源头控制。

  • I2C:上拉电阻不是随便选的,要算上升时间;死锁了别急着断电,试试手动翻SCL;上升沿太慢容易被干扰误触发。

  • SPI:低速随便飞,高速要讲究信号完整性------走线等长、阻抗匹配、远离干扰源。CS别悬空。

  • CAN :终端电阻两端各120Ω(总线上很多设备点,只接首尾两个节点),一个不能少;总线用双绞线走直线拓扑,工业场景上隔离。

通信硬件层的坑,调试软件解决不了,只能在画原理图和Layout的时候提前预防。

相关推荐
天天爱吃肉82181 小时前
【汽车研发测试工程师|Python自动化实测全套脚本(CAN解析+数据处理+自动出报告)】
大数据·python·功能测试·嵌入式硬件·汽车
三佛科技-134163842121 小时前
AIP8P005B 与FT60E112A(8位I/O型单片机)对比分析,FT60E112A能否兼容替代AIP8P005B?
单片机·嵌入式硬件·物联网·智能家居·pcb工艺
fffzd1 小时前
STM32:串口--轮询模式
stm32·单片机·嵌入式硬件·串口·hal库·轮询模式
municornm2 小时前
单片机IO不够?ULN2003A救急方案
单片机·嵌入式硬件
m0_618526202 小时前
矩阵RGB三色LED驱动芯片CH466(SPI模式)
单片机·嵌入式硬件
Geometry Fu2 小时前
《物联网安全》第6章 入侵检测技术
网络·物联网·安全·ips·入侵检测·ids
染予2 小时前
实现功能:给stm32F427zgt6开发板配置网络,电脑可以ping通开发板
stm32·单片机·嵌入式硬件
Hotchip_MEMS2 小时前
单节锂电池充电管理:如何平衡充电速度与电池寿命
人工智能·单片机·嵌入式硬件·物联网
ι:2 小时前
Codex 接管嘉立创EDA 并复现 STM32 Blue Pill 学习底板的完整教学
stm32·嵌入式硬件·学习