news 2026/10/17 10:05:14

一文搞懂ARM通信协议:串并行、同步异步、单工双工

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一文搞懂ARM通信协议:串并行、同步异步、单工双工

干嵌入式这些年,新来的同事问得最多的问题,往往不是哪个外设寄存器怎么配,反而是通信协议里最基础的那几个概念。串行还是并行、同步还是异步、单工还是双工,这三个维度基本构成了ARM芯片跟外界打交道的全部规则。看协议手册时满屏的SCLK、MOSI、MISO、波特率、起始位,归根结底都是在围绕这几个概念打转。搞不明白它们,代码写出来也常常是"看起来能用,换个环境就翻车"。

这篇文章我就用做项目时的实际体会,把串并行、同步异步、单工双工彻底讲透。不堆理论、不念PPT,每个概念都结合ARM里常见的UART、SPI、I2C、RS-485这些具体外设来说,平时踩过的坑也会一并交代清楚。不管你是刚接触ARM的小白,还是被波形折磨过的老手,看完应该都能理顺这套底层的通信逻辑。

1. 通信协议的三组基础维度

1.1 用寄快递的过程来理解通信

先把这三个概念拆开。通信的本质就是两方之间传递数据,ARM芯片内部有CPU、内存、各种外设,这些部件之间要传数据,芯片跟外部的传感器、其他芯片、上位机也要传数据。凡是传数据,就绕不开三个问题:数据是排队走还是一排走、双方靠什么对齐节奏、数据能不能同时双向流动。

这三个问题分别对应串并行、同步异步、单工双工。我用寄快递来类比:你需要把一批文件发给另一个人。并行通信就好比你雇了八个人,每人拿一页文件,同时出发送到对方手里,速度理论上是八倍,但你需要保证八个交通路线同样顺畅,任何一路堵车、文件顺序出错,整个批次就乱了。串行通信就好比只雇一个快递员,一页一页挨个送,路线只有一条,但管理简单、不容易乱。

同步和异步像是收发双方怎么对表。同步通信是手里捏着同一个节拍器,你打一拍我走一步,节奏完全对齐。异步通信是双方各自带表,只要表走得差不多快就行,收到一个起始信号就开始数秒。单工、半双工、全双工则是对讲机、电话和单向广播的区别:单工只能一个人说另一个人听,对讲机按下按键才能说话;半双工能对话但同一时刻只能一个人说;全双工是电话,两边同时说同时听,互不干扰。

这个类比虽然简化,但把核心逻辑说清楚了。真正的通信协议,就是在这三个维度里分别做选择,然后把选择结果用电气层面和帧格式层面的规则固定下来。

1.2 三组概念是独立组合的

这三组概念不是互斥关系,而是可以自由组合的维度。ARM里最常见的UART就是串行、异步、全双工;SPI是串行、同步、全双工;I2C是串行、同步、半双工。并行不是没有,像早期的存储器总线、液晶屏并口接口,就是并行、同步、半双工或者全双工。

理解到这一层,再看协议手册就会轻松很多。手册里画的那张时序图、管脚定义表、数据帧格式,其实就是把这三组选择的答案用图形和数据规定出来了。你真正需要判断的,只是某个具体场景下应该选哪个组合。比如芯片引脚紧张,就尽量用串行;要求实时性又不想加额外的时钟线,就可能要用UART这种异步方案;总线要挂很多从设备且不想占用太多引脚,I2C的地址机制就是个好选择。

所以学习ARM通信协议,不要一个一个死记硬背,先把这三组维度刻在脑子里,再去对照具体协议,效率会高很多。

2. 串行与并行:ARM引脚背后的取舍

2.1 并行通信为什么慢慢被边缘化

并行通信的含义是在同一时刻通过多条线路同时传输多个数据位,8位数据就需要8根数据线,16位就需要16根。听起来带宽很诱人,但真正的工程代价远不止多几根线。

第一是引脚资源。一颗ARM芯片引脚数量是固定的,一般民用级芯片也就几十到一百来个引脚,除去电源、地、调试、复位这些固定开销,留给通信的引脚非常宝贵。如果每个通信接口都要占用一二十个引脚,同时挂几个外设就没法玩了。

第二是信号同步问题。并行信号位宽越大,数据线之间的长度差、PCB走线的寄生电容电感差异就越明显,结果就是有的位先到达、有的位后到达。位与位之间不再对齐,接收端就很难在同一个时钟沿把全部数据抓对。频率越高,这个问题越严重。做过高速PCB的人都知道,等长布线是一件极其痛苦的事情。

第三是抗干扰能力。多根线并行布线,线间距近,串扰没法避免,而且外部噪声更容易通过长线耦合进来。在工业现场,并行总线往往跑不了很高频率,反而成为整个系统的瓶颈。

也正是因为这些问题,并行通信如今只在非常特定的场合存在:芯片内部的总线、DDR内存接口、某些液晶屏RGB接口。而在芯片与芯片之间、板卡与板卡之间,并行已经几乎绝迹。

2.2 串行通信靠什么赢回来

串行通信每次只传一个bit,听起来吞吐率天然吃亏,但工程师用两个方法把劣势逆转了。

第一个方法是提高时钟频率。既然只有一根数据线,那就让它拼命跑快,用高频率来弥补位宽的损失。UART跑个几Mbps很轻松,SPI可以跑到几十兆甚至上百兆bps,而像USB、PCIe这些串行总线,速率已经到了几十Gbps的量级。一根线的布线比八根线简单太多,等长要求也没那么苛刻,信号完整性反而好做。

第二个方法是引入差分信号和编解码技术。像RS-485、USB、以太网这类串行协议,用的是两根线传输一个信号,一根发正相、一根发反相,接收端把两个信号相减还原数据。差分传输抗共模干扰能力很强,而且允许用低电压摆幅实现更高速度。再加上8B/10B、64B/66B这类编码技术,或者曼彻斯特编码,就能把时钟信息嵌进数据流里,进一步压缩了线路数量。

这两个方法叠加之后,串行通信不仅省引脚,而且在速率、距离、抗干扰性上全面反超了并行。现在ARM芯片上几乎所有通信外设都是串行的,UART、SPI、I2C、CAN、USB、以太网,没有例外。

2.3 ARM工程里怎么选

在具体的ARM设计里,选串行还是并行,其实大部分场景已经由外设类型决定了。

比如挂一个温湿度传感器,通常就用I2C或者单总线,两根线甚至一根线搞定,功耗低、接线少。接一个外部Flash存储芯片,图形显示数据量不大可以用SPI,写固件、存大数据,就考虑QSPI或者SDIO。接并口液晶屏,如果MCU引脚够多、对刷新率要求又高,可能会考虑FSMC或LCD接口,这是为数不多还在用并行的地方。

真正需要纠结的是带宽评估。选串行接口前,先估算一下实际业务载荷,也就是每秒真正要传多少有效字节。然后留出至少30%的余量,因为协议本身有开销,比如UART每个字符有起始位停止位,SPI可能需要填充间隔,I2C有地址帧和应答位。余量不够,系统稍微一忙就会出现缓冲溢出、丢数据的问题。

个人经验是:宁可选高一个档次的串行接口,也不要为了省成本去碰并行。除非你非常确定引脚足够、走线可控,否则后期的PCB调试成本会远超省下的那点物料费。

3. 同步与异步:时间基准从哪里来

3.1 异步通信的时间基准:靠波特率对齐的UART

异步通信最典型的代表就是UART。它的特点是没有单独的时钟线,两条线各自独立,发送方和接收方各自维护一个时钟。问题来了:大家频率不一样怎么办?UART的解决办法是提前约定一个波特率,也就是每秒传输多少个符号,双方都按照这个速率来采样,通信前先把UART的波特率寄存器配置成同一个值。

但光有波特率还不够,接收端必须知道从哪个时刻开始数bit。UART的帧格式就是为此设计的。空闲时线路处于高电平,发送方要发数据时先把电平拉低一位,这一个低电平就是起始位,接收端在下落沿触发采样,然后按照波特率在每一位的中间时间点连续采样数据位、校验位,最后遇到停止位(高电平)算一个字符结束。

这个机制挺精巧,但代价是效率。每个字符至少要额外发送起始位和停止位,如果还带校验位,额外开销就更大了。10个bit里可能只有8个bit是有效数据,实际吞吐率只有波特率的80%。另外,异步通信要求双方时钟误差小,一般串口标准建议累积误差不要超过2%左右,否则采样点会逐渐偏移,到最后几个数据位上就可能采错。

异步通信其实非常依赖"每个字符都重新同步一次"这个机制。虽然两个端的时钟不是完全一样,但是每个字符都有新的起始位来对齐,误差不会跨字符累积。这也是为什么UART传输大块数据时,中间有停顿也没关系,只要字符内部节奏对得上就行。

3.2 同步通信的时间基准:时钟线说了算的SPI与I2C

同步通信的原理是发送方直接把时钟信号给对方。最典型的就是SPI,它有独立的SCLK时钟线,主机输出时钟沿,从机在对应沿上移出或移入数据。这样一来双方根本不需要波特率匹配,只要时钟沿没过快、超过器件极限,基本不会错位。

SPI还额外提供了四种模式,通过CPOL(时钟极性)和CPHA(时钟相位)两个参数来决定时钟空闲电平是低还是高、数据在上升沿采样还是在下降沿采样。主从双方必须完全一致,否则读回来的数据全是乱的。这个没有谁对谁错,只有匹配不匹配。

I2C是另一类同步通信,它只有两根线:SCL时钟线和SDA数据线,严格来说算半同步半异步。因为I2C在传输过程中由主机产生SCL时钟,从机还能通过拉低SCL来实现时钟延展,也就是慢下来的从机可以强制主机等待。这个机制叫clock stretching,是I2C同步性的一种灵活变通。

同步通信的优势是效率高。数据帧里不需要频繁加起始位停止位,可以连续传一大段,配上DMA之后,CPU几乎不用介入。缺点是要占用一根时钟线,而且时钟线对布线有一定要求,过长或干扰严重时,时钟抖动会直接导致采样错误。

3.3 同步模式选择的几个经验

关于SPI的CPOL和CPHA,我的建议是别背寄存器手册里的表格,直接看从机数据手册里的时序图。时序图上会画出SCLK的默认电平,以及数据在哪个边沿稳定、在哪个边沿变化。抓住一个原则:采样一定要采在数据稳定的时候,绝不能在数据发生跳变的边沿去采样。

CPOL决定了空闲时SCLK是高还是低,CPHA决定了相位是第一个沿还是第二个沿采数据。实际项目里如果发现SPI读回的数据整体错位,或者在特定温度下偶发错误,优先排查这两项配置。

I2C的同步性里还要注意时钟延展这个问题。不少MCU在作为I2C从机时,如果不小心把SCL拉低太久,会卡住主机。排查的时候用逻辑分析仪看波形,如果发现SCL持续低电平超出一帧的正常长度,多半是从机端在延展时钟或者死锁了,这时候就要查从机固件是否在中断里做了耗时的操作。

4. 单工、半双工、全双工:数据流向决定总线设计

4.1 三种方向模式到底怎么定义

单工就是数据只能往一个方向传输,另一端只能接收,相当于收音机广播。ARM系统里的单工场景不多,但确实存在,比如只读传感器向MCU连续上报数据,或者MCU向LED驱动芯片发送配置命令,另一方不需要回数据。

半双工是双方都可以发送,但同一时刻只允许一个方向占用总线,相当于对讲机。要说话就得按下按键,说完松开别人才能说。总线本身只有一条数据通路,A发B收,和B发A收是分时复用的。

全双工是两条独立的数据通路,A发的同时也能收,B也一样。UART就是这么干的,一根TX一根RX,发送和接收互不干扰。SPI四根线里有MOSI和MISO两根独立数据线,也天然支持全双工。

判断一个协议是哪种模式,最简单的办法是看它有几根数据线。数据线只有一根,几乎没有例外地是半双工。数据线有两根并且方向相反,才有可能全双工,还要看协议是否允许同时收发。

4.2 典型ARM外设的数据方向特征

UART在标准三线接法下是全双工:TXD发送、RXD接收,两边完全独立。工程上偶尔有人把UART当单工用,只发不收,这当然可以,但物理能力是全双工的。

SPI是全双工,因为发送和接收有各自的线。值得注意的一个细节是SPI在发送的同时必然在接收,即使你根本不在乎从机回的数据,主机的接收缓冲区里也会进去同样数量的字节。处理不干净,就会导致缓冲区溢出。

I2C就是典型的半双工。SDA只有一根线,读和写命令都不能同时进行。每次传输都是主机先发起开始条件,再发送从机地址和读写位,然后根据读写位决定方向。由于只有一条线,收发切换时还要处理总线占用、方向转换时间这些麻烦事。

RS-485是另一个很常见的半双工场景。它物理上是差分对,但挂在一根双绞线上的多个节点共享同一对线,所以协议层面必须规定好谁在什么时候发送。MCU接RS-485收发器时,需要通过DE/RE引脚控制发送使能,发送完成后要立刻切换回接收状态,否则会一直占着总线。

4.3 半双工切换时序的工程细节

半双工最坑的地方在于切换时序。以RS-485为例,很多人第一次调不通,就是因为发送完之后马上把引脚切到接收,最后一个字节还没发完,总线就释放了。收发器里通常有发送延时和接收延时,都是微秒级的,建议在发送完最后一个字节后,至少等待一个字符帧的时间再切换方向。有些控制器还会配置RS-485的方向控制自动功能,配合DMA和空闲中断会更稳。

I2C的半双工切换也有讲究。主机发送读命令后,从机要接管SDA并向主机回数据,中间有没有空隙由ACK位来衔接。调试的时候最怕SDA被某个设备拉死,现象是整个I2C总线上任何操作都没有ACK。排查这种问题,首先要看是不是有设备地址冲突,或者某从机内部崩溃后一直占着SDA不放。

全双工虽然省心,但在调试时也有自己的坑。比如UART的TX和RX,有人会想当然地认为A的TX接B的RX就行,接反了或者把信号线与地线弄混,数据完全不通。接完之后先回环测试一下:把本地TX和RX短接,自发自收,如果正常说明串口本身没问题,再往外设上接。

5. 常见问题排查与实战避坑

5.1 串口乱码的排查顺序

串口乱码是最常见的通信故障,没有之一。很多人第一反应是波特率不对,这当然对,但不全面。我的排查顺序是:先量电平,再查接线,最后谈波特率。

用万用表测一下空闲状态下TXD引脚的电平,正常的UART空闲时是高电平,如果量出来是0V,那可能是芯片没工作、引脚被拉死,或者直接接到了RS-232电平设备上。TTL电平的0V到3.3V和RS-232的负逻辑完全相反,不经过电平转换芯片直接互连,出来的全是乱码。

接线确认无误之后,再考虑波特率误差。ARM芯片的UART波特率是通过时钟分频出来的,如果芯片主频配置变了,而波特率寄存器没跟着变,实际波特率就跟标称的差很远。用示波器测TXD引脚的数据位宽度,稳定值是1除以波特率,比如9600波特率时每个位宽约104微秒。实际测出来差得超过2%,就要修正时钟配置。

最后还有一种让人头疼的乱码:字符偶尔错一个,比如把0x55收成0x94。这种情况很可能是地线阻抗过高或者干扰耦合进来的。UART收发双方之间必须保证良好共地,否则信号电平的参考点不一致,通信质量必然恶化。

5.2 SPI数据错乱的排查方法

SPI出错比UART含蓄,因为多半不是完全乱码,而是"数据整体对不上"。比如你读寄存器得到的数据像是左移了一位、丢了最高位之类。

这种绝大多数是CPOL和CPHA配置问题。我的建议是先把模式固定在主机模式,然后用示波器或者逻辑分析仪抓SCLK和MOSI的时序,对照从机手册的要求,看数据变化边沿和采样边沿是否一致。最土但最有效的办法:写一个简单的回环测试,把MISO和MOSI短接,发一串已知的数据,如果能读回来,就没理由说硬件有问题。

拆开分析波形。当数据读回来整体变成一个前导位丢了或者多出来一个位,大概率是采样沿选错了。当数据读回来全是0xFF或者0x00,先看从机有没有被CS片选拉低,再看从机是否进入了正确的配置状态,最后再怀疑接线。

SPI还有一个隐蔽的坑是高速模式下的信号质量问题。频率上去之后,线长、分支、串接电阻都会影响波形。时钟边沿不够陡或者振铃严重,会在高位时出现偶发错误。这时候可以降低SPI时钟频率验证,如果降频就正常,说明是信号完整性问题,不是逻辑问题。

5.3 总线死锁与交替发送的坑

I2C死锁是半双工总线最典型的故障。现象是主机的读操作一直收不到ACK,用逻辑分析仪抓SDA,发现它一直低电平。这是因为某个设备在工装中出现异常,把SDA拉低了,让其他设备没法启动起始条件。

排查方法:把所有I2C设备从总线上一一摘除,摘一个测一次,基本能定位到是谁干的。如果没有设备能摘,试一下给I2C外设做一次总线恢复操作,一般MCU外设库里都会有,做法是把SCL连续翻转9个脉冲,让卡在中间状态的从机退出。这个操作很多时候能临时救回来,但根本问题还是要去查从机为什么会锁死,比如供电不稳、复位不充分。

RS-485这类差分半双工总线,还有一个容易被忽略的问题:终端电阻和偏置电阻。总线空闲时所有节点都没驱动,A、B之间电平处于不确定状态,这时如果某个节点恰好检测到一个起始位,就可能收到一个杂散的0x00帧。解决方法是加偏置电阻让总线空闲时保持确定电平,或者在协议层做帧起始和帧结束校验,丢掉非法帧。

另外,半双工切换时的死区时间要特别小心。主控判断发送完成,通常用发送寄存器空标志和数据寄存器空标志,但发送移位寄存器可能还在工作。稳妥做法是使用传输完成标志(TC),或者在连续发送模式中用DMA传输完成中断然后加一点延时,再去翻转方向控制引脚。

5.4 用逻辑分析仪抓波形的实用技巧

调试通信协议,逻辑分析仪比示波器好使。因为协议波形是时间维度的数字信号,逻辑分析仪可以连续记录很长时间,还能按协议解码,直接把UART的帧、SPI的字节、I2C的总线状态解析出来。

抓波形有几个技巧。采样率不要只管设高,要跟记录时长权衡。UART 115200波特率下,每个字符大约87微秒,采样率1MHz就足够看清楚了,也就是一个bit采8到9个点。SPI如果跑到20MHz,采样率至少要到100MHz,不然边沿抓不准。

触发条件也很重要。UART抓发送,可以设置下降沿触发,抓的就是起始位。SPI抓通信,用CS片选信号的下降沿触发最方便。I2C则用起始条件触发。触发设好了,频繁的数据流里才不会被无关波形淹没。

现在市面上的逻辑分析仪软件基本都支持协议解码,但解码结果只是辅助,最终判断还是要回到波形本身。特别是SPI的CPOL、CPHA这些模式问题,解码器可能因为配置跟你抓到的实际值不一致而误判,这时候裸眼看波形才是最可信的。

6. 我自己的一些经验体会

聊到这儿,串并行、同步异步、单工双工这几个概念看起来简单,真正用起来才知道水有多深。我自己的体会是,学通信协议一定不要只背概念,要拿着逻辑分析仪抓波形,把协议手册里的时序图跟实际波形对照起来看一遍。见过起始位长什么样、SCLK边沿跟数据变化怎么对齐、SDA被拉低是什么现象,以后再遇到通信问题,脑子里是有画面的,排查起来快很多。

三组维度在工程里往往要一起看。一个总线设计得合不合理,不是看某一个维度,而是看它们组合起来是否匹配实际场景。比如一个低功耗传感器网络,用UART全双工虽然简单可靠,但引脚占用多、线缆成本高;换成半双工的RS-485,布线省了、抗干扰强了,代价是软件上要处理方向切换。没有绝对的好坏,只有适不适合自己的硬件规模和成本预算。

还有一个建议是善用芯片自带的诊断能力。很多ARM芯片的UART有接收超时中断,SPI有模式错误标志,I2C有总线错误检测,把这些中断和标志充分利用起来,做一个通信状态看门狗,出问题的时候就能自动恢复。别一味依赖人工排查,好的容错设计能让系统在恶劣环境下跑了几个月都不出岔子。

最后再说一个实操中反复验证过的小技巧:新板子回来,先把所有通信接口都做一遍自测,UART做回环、SPI做回环、I2C读从机设备ID,全通过了再往上层应用上堆功能。这一步做好,后面软件开发能省掉一半的联调时间。通信协议基础打牢了,整个项目的地基才稳,后面加功能、提性能、换平台,都会从容很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 10:03:53

聚类算法实战指南:无监督学习原理、选型与工程落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 10:03:16

双节锂电主动均衡设计:MP2642+STM32F415RG系统级实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 10:02:45

Android Camera HAL3架构拆解:从请求-响应模型到Pipeline实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 10:02:38

OCR表格扭曲矫正:从几何畸变识别到四点透视校正

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 10:02:02

C#异步心跳连接实战:保活、探活与自动重连

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 10:01:14

彻底讲透二叉树遍历:前序中序后序的递归与迭代核心

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华