目录
- 前言
- 一、通信专题预备知识:从基础概念到UART宏观理解
- 1.1 串行通信与并行通信
- 1.1.1 并行通信的局限
- 1.1.2 串行通信的优势
- 1.2 同步通信与异步通信
- 1.2.1 同步通信
- 1.2.2 异步通信
- 1.3 通信拓扑与双工模式
- 1.3.1 单工模式
- 1.3.2 半双工模式
- 1.3.3 全双工模式
- 1.3.4 UART 的双工特性
- 1.4 UART 核心定义与特性总结
- 1.4.1 官方定义
- 1.4.2 核心特点
- 二、串口通信的宏观认知与硬件架构
- 2.1 USART 在 MCU 内部的定位
- 2.2 通信协议的本质:约定与规则
- 三、UART 与 USART 的辨析及物理连接
- 3.1 概念辨析:同步与异步
- 3.2 物理连接方式
- 四、串口通信的核心机制与微观原理
- 4.1 GPIO 引脚复用机制
- 4.2 数据传输方向与低位先发原则
- 五、波特率匹配:通信节奏的生死线
- 结语
前言
大家好啊,我是云泽Q,欢迎阅读我的文章,一名热爱计算机技术的在校大学生,喜欢在课余时间做一些计算机技术的总结性文章,希望我的文章能为你解答困惑~
一、通信专题预备知识:从基础概念到UART宏观理解
从这篇文章开始就是 USART 通信。在深入具体的寄存器配置和代码实现之前,我们需要先铺垫一些后续通信话题中必不可少的常规概念。这些概念不仅适用于 USART,在 I2C、SPI 等其他通信协议中也会反复遇到。同时,我们还需要从宏观上理解 MCU、GPU、板子以及 Trunk(即 USART)四方之间的关系,并掌握比特率与波特率的区别。只有具备了这些背景知识,我们才能递进式地理解串口通信的数据帧格式、收发原理以及阻塞发送接收的理论基础。
1.1 串行通信与并行通信
在数字电路的早期,并行通信曾经占据主导地位,但随着技术的发展,串行通信凭借其独特的优势成为了主流。我们需要从物理传输形式的角度来理解这两者的区别。
1.1.1 并行通信的局限
并行通信是指数据在多位数据线(如 8 根、16 根或 32 根)上同时传输。虽然看起来一次能传很多位,但在实际工程应用中,它存在明显的短板:
- 成本高昂:需要大量的物理连线,布线复杂,占用 PCB 面积大。
- 信号干扰:多根导线并行排列时,电流产生的磁场会相互影响,导致信号串扰,尤其是在高频下更为严重。
- 同步困难:由于每根线的物理长度和电气特性难以做到绝对一致,信号到达接收端的时间会有微小差异( skew ),导致接收端必须等待最慢的那一位信号稳定后才能采样,这限制了整体速率的提升。
- 扩展性差:如果需要增加数据位宽,就必须重新布线。
- 功耗大:驱动多根线路翻转需要消耗更多的能量。
1.1.2 串行通信的优势
串行通信则是将数据在一根线上按位依次传输。虽然单次只传一位,但它解决了并行通信的诸多痛点:
成本低:连线极少,例如 UART 仅需 TX 和 RX 两根线。
抗干扰强:线少,信号间的磁场干扰大幅降低。
速率极高:得益于抗干扰能力的提升和差分信号等技术的应用,串行通信的频率可以做得非常高。电信号在导线中的传播速度接近光速,通过提高频率,单位时间内传输的数据总量远超并行通信。
扩展性好:想要传输更多数据,只需延长传输时间即可,无需增加物理线路。
目前主流的通信接口,如 I2C、SPI、USB、PCIe 等,本质上都是串行通信。这里需要特别区分一个概念:“串行”是一种物理传输形式,而“串口”(如 UART)是一套具体的通信协议标准,二者不能混为一谈。
1.2 同步通信与异步通信
理解了串行与并行的区别后,我们需要进一步探讨数据是如何被“对齐”和“识别”的。这就引出了同步与异步的概念。在 STM32 等 MCU 开发中,区分这两者最简单直观的方法就是看硬件上有没有时钟线。
1.2.1 同步通信
同步通信依赖于额外的时钟信号线(CLK)。
- 工作原理:发送方在输出数据的同时,输出一路时钟信号。接收方不关心时间过了多久,而是严格根据时钟线的边沿(上升沿或下降沿)或电平状态来采样数据线上的值。
- 特点:就像两个人一起走路,必须步调一致。时钟线就是那个喊口号的人,数据线跟着节奏走。只要有 CLK 线参与同步,就是同步通信。
1.2.2 异步通信
异步通信没有时钟线,它完全依赖收发双方预先约定的“节奏”来工作。
- 工作原理:既然没有时钟线告诉接收方“现在该读数据了”,那么双方必须提前商量好每一位数据持续多长时间。这个时间标准就是波特率(后面会细说,这里暂时提出来)。例如,双方约定波特率对应每位数据持续 1 毫秒,那么当接收方检测到起始信号后,就会每隔 1 毫秒去读取一次数据线上的电平。
- 核心判断依据:硬件上不存在时钟线,仅靠数据线(TX/RX)进行通信。UART 就是典型的异步通信,因为它只有 TX 和 RX,没有 CLK。
1.3 通信拓扑与双工模式
在通信系统中,数据的流向决定了通信的模式。我们可以通过生活中的例子来形象地理解单工、半双工和全双工这三个核心概念。从逻辑关系上讲,全双工可以看作是半双工的一种特殊情况,而半双工又是单工的特殊情况,但在工程定义中我们通常将它们并列区分。
1.3.1 单工模式
单工是指数据只能沿着一个固定的方向传输,永远不能反向。
- 生活案例:课堂授课。老师在讲台上讲,学生在下面听。这种情况下,只允许老师说话(发送),学生只能听(接收),学生不能通过同一个信道反向给老师讲课。这就是典型的单工模式。
- 硬件特征:只有一条单向的数据通路。
1.3.2 半双工模式
半双工是指数据可以双向传输,但在同一时刻只能进行一个方向的操作。要么 A 发 B 收,要么 B 发 A 收,不能同时进行。
- 生活案例:日常朋友间的对话。当你说话时,朋友在听;朋友说话时,你在听。虽然你们都能说也能听,但正常沟通时不会两个人同时开口抢话,否则谁也听不清。这种“你说我听,我说你听”的交替模式,就是半双工。
- 硬件特征:通常只有一根数据线,或者两根线但在逻辑上互斥使用。
1.3.3 全双工模式
全双工是指数据可以在两个方向上同时传输。A 发送给 B 的同时,B 也可以发送给 A,互不干扰。
- 生活案例:马路边的争吵。当两个人发生激烈冲突时,往往是你骂我一句,我同时也骂你一句,甚至两个人都在不停地输出,同时也在接收对方的辱骂。这种“边说边听”、收发同时进行的状态,就是典型的全双工。
- 硬件特征:拥有独立的发送路径和接收路径。
1.3.4 UART 的双工特性
回到我们的主角 UART,它是一种全双工的通信方式。因为 UART 在物理上拥有独立的 TX(发送)线和 RX(接收)线。这两根线是解耦的,TX 线专门负责发,RX 线专门负责收,互不冲突。因此,在使用 UART 通信时,我们可以实现真正的同时收发。
1.4 UART 核心定义与特性总结
综合上述概念,我们可以对 UART 做一个精准的定义和特性梳理。
1.4.1 官方定义
UART 的全称是 Universal Asynchronous Receiver/Transmitter,即通用异步收发器。它是 MCU 内部的一个片上外设,主要负责将并行数据转换为串行数据发送出去,或者将接收到的串行数据转换为并行数据供 CPU 处理。在实际芯片手册中,你可能会看到 USART(Universal Synchronous/Asynchronous Receiver/Transmitter),它比 UART 多了一个同步模式的功能,但在大多数通用场景下,我们主要使用其异步功能,所以常统称为串口或 UART。
1.4.2 核心特点
- 异步通信:如前所述,没有时钟线,依赖约定的波特率进行位同步。
- 串行通信:数据在单根线上按位顺序传输。
- 一对一通信:这是 UART 的一个重要限制。每一个串口单元在同一时刻只能与另一个串口单元进行点对点通信。它不像 I2C 或 SPI 那样具备硬件地址寻址能力来支持一主多从。如果要连接多个设备,通常需要软件模拟或多路复用。
- 全双工:拥有独立的 TX 和 RX 线路,支持同时收发。
- 唤醒机制:UART 模块通常具备唤醒功能,可以在低功耗模式下通过特定的唤醒序列被激活,这对于电池供电设备非常重要。
二、串口通信的宏观认知与硬件架构
接下来需要先建立起对串口通信的宏观认知。这不仅仅是关于代码怎么写,更重要的是理解数据在芯片内部是如何流转的,以及它与整个 MCU 系统的关系。
2.1 USART 在 MCU 内部的定位
首先我们要明确一个概念:USART(Universal Synchronous/Asynchronous Receiver Transmitter)是 MCU 内部的一个片上外设。
当我们打开 STM32 的参考手册,查看“存储器与总线结构”图时,可以清晰地看到整个系统的拓扑。在这个架构中,Cortex-M3 内核通过 ICode、DCode 和 System 总线连接到总线矩阵。而我们的 USART 外设,正是挂载在这个庞大的总线网络之下的。
具体来说,STM32F103ZET6 这款芯片内部默认包含了多个 USART 模块(如 USART1 到 USART5)。它们并不是独立于 MCU 之外的孤岛,而是作为片上资源,通过 AHB 系统总线、桥接器(Bridge 1/2)最终挂载在 APB1 或 APB2 总线上。
- APB2 总线:通常挂载速度较快或较重要的外设,例如 USART1、GPIOA~G 等。
- APB1 总线:通常挂载 USART2、USART3、UART4、UART5 等。
这意味着,CPU 可以通过读写特定的内存地址(即寄存器)来直接控制这些 USART 模块。每一个 USART 都可以独立工作,互不干扰。至于具体的引脚分布和硬件清单,我们需要查阅《数据手册》中的“器件一览”表。以 STM32F103Zx 系列为例,它明确标注了拥有 5 个 USART/UART 接口。这就像是一个大家庭里有 5 个专门负责对外联络的“通讯员”,每个通讯员都有自己的职责范围。
2.2 通信协议的本质:约定与规则
有了硬件基础,我们还需要理解通信的灵魂——协议。
为什么两个设备连在一起就能说话?举个通俗的例子:如果我是中国人,我说中文;对面站着一个葡萄牙朋友,他说葡萄牙语。虽然我们在物理上都是人类,都有嘴巴和耳朵(硬件连通),硬件连接没有问题,但因为语言不通(协议不同),我们依然无法交流,完全是“牛头不对马嘴”。
设备间的通信也是同理。仅仅把线连上是不够的,通信双方必须遵守一套预先约定好的规则。这套规则决定了:
通信双方发送和接收数据快慢的问题(波特率)
接收端怎么知道发送端什么时间开始或结束数据发送的?一次计划携带多少数据(帧格式)
只有当双方都严格遵守这些约定时,发送端发出的高低电平序列,才能在接收端被正确解读为有意义的信息。这一点不仅适用于串口,对于后面的 SPI、I2C 等所有通信接口都是通用的真理。GPIO 只是单纯地输出高低电平点个灯,而涉及通信的外设,核心都在于“协议约定”。
三、UART 与 USART 的辨析及物理连接
这里再细致说一下它们的区别
3.1 概念辨析:同步与异步
从定义上讲:
- UART:通用异步收发器。它只支持异步通信,不需要时钟线,完全依靠双方约定的波特率来同步数据。
- USART:通用同步/异步收发器。它功能更强大,既支持异步模式(当作 UART 用),也支持同步模式(带 CLK 时钟线)。
但在 STM32 的实际应用场景中,绝大多数时候我们使用的都是它的异步模式。因为同步模式需要额外的时钟线,应用场景相对较少。所以,虽然芯片手册里写的是 USART,但在实际工程和交流中,我们常把它等同于 UART 来使用。大家在配置时,只要不涉及同步时钟线,就可以把它们看作是一回事。
3.2 物理连接方式
理解了概念,我们来看物理连接。无论是 UART 还是 USART,最基本的连接都需要三根线:
- TX (Transmit):发送端。
- RX (Receive):接收端。
- GND (Ground):地线。
这里有一个极易犯错的细节:交叉连接。
MCU 的 TX(发送)必须连接到外部设备的 RX(接收);MCU 的 RX(接收)必须连接到外部设备的 TX(发送)。这就好比两个人打电话,我的嘴巴(TX)要对着你的耳朵(RX),你的嘴巴(TX)要对着我的耳朵(RX)。如果 TX 接 TX,RX 接 RX,那是绝对通不了信的。
如果是USART 的同步模式,除了上述三根线,还需要多一根CLK(时钟线),用于同步数据传输的节奏。但在异步模式下,这根线是不需要的。
四、串口通信的核心机制与微观原理
这一部分是我们理解串口工作的重中之重,主要包含引脚复用机制和数据传输的时序逻辑。
4.1 GPIO 引脚复用机制
很多兄弟会问:USART 的信号是怎么从芯片里跑出来的?它并没有自己独立的引脚啊。
答案是:复用(Alternate Function)。
在 STM32 的内部结构中,GPIO 引脚不仅仅能作为普通的输入输出口,它们还具备“第二职业”。当我们配置 USART 时,实际上是在使用 GPIO 引脚的复用功能。
- 发送端 (TX):对应的 GPIO 引脚会被配置为“复用推挽输出”模式。此时,引脚的输出控制权从普通的 GPIO 数据寄存器移交给了 USART 外设。USART 内部产生的电平信号直接驱动引脚上的 PMOS/NMOS 管,向外发送波形。
- 接收端 (RX):对应的 GPIO 引脚会被配置为“浮空输入”或“上拉输入”模式。外部信号直接进入引脚,通过施密特触发器整形后,送入 USART 的接收移位寄存器。
所以,在配置代码时你一定会发现:配置 USART 之前,必须先开启对应 GPIO 端口的时钟,并配置好引脚模式。这就是因为 USART 是“寄生”在 GPIO 引脚上的,没有 GPIO 的物理通路,USART 的信号就出不去也进不来。
4.2 数据传输方向与低位先发原则
在串口通信的微观世界里,数据的传输是有严格方向的。这里必须建立一个极其重要的认知:低位先发(LSB First)。
假设 MCU 要发送一个字节的数据0x55,其二进制序列是0101 0101。
在示波器上观察 TX 引脚的波形,或者在逻辑分析仪上看数据流,你会发现:
- 最先发出去的是最低位(Bit 0)。
- 最后发出去的是最高位(Bit 7)。
这意味着,先发出去的数据位在时间轴的最右边(也就是波形的起始位置),但在数值逻辑上它是最左边的那一位。整体来看,数据像是在向右移动一样被推送到线路上。
这个“低位先发”的规则是串口协议的铁律,不能搞反。如果接收端按照高位先发来解析,那收到的数据就会完全错乱(比如0x55可能会变成别的数,或者校验错误)。所以在分析波形时,一定要时刻记得:时间轴越早出现的脉冲,代表的是二进制数的越低权重的位。
五、波特率匹配:通信节奏的生死线
为什么有时候通信会乱码?
这就引出了串口通信中最关键的参数:波特率(Baud Rate)。
波特率本质上就是通信的“节奏”或“语速”。它定义了每秒钟传输多少个符号(在标准 UART 中,1 个符号 = 1 个比特)。
让我们回到那个“中国人和葡萄牙人”的例子,这次换成节奏的问题:
- 发送方:“我语速很快,1 秒钟发 8 个高低电平变化。”
- 接收方:“但我耳朵反应慢,我以为你是 2 秒钟才发 1 个变化。”
结果会怎样?
发送方已经噼里啪啦发完了一串数据(比如发了 8 个 bit),接收方可能才刚刚检测到第一个变化的边沿,或者把发送方的 8 个 bit 误读成了 4 个 bit。这就好比两个人跳舞,一个人跳得快,一个人跳得慢,步子完全踩不到一起,最后肯定乱套。
这就是波特率不匹配的后果。
- 如果发送快、接收慢:接收端会漏掉数据,或者把多个 bit 当成一个 bit 读。
- 如果发送慢、接收快:接收端会在同一个 bit 的电平期间采样多次,导致读出一堆重复的错误数据。
因此,所谓的“约定”,在物理层面上最直接的体现就是:通信双方的波特率必须严格一致。无论是 9600、115200 还是其他数值,只要有一方设错了,通信就会失败。
总结一下,串口通信的宏观过程就是:CPU 将数据写入 USART 寄存器 -> USART 按照“低位先发”的规则 -> 控制复用的 GPIO 引脚 -> 以双方约定好的“波特率”节奏 -> 将高低电平序列发送到线路上。