STM32 串口通信 (UART) 全栈底层复习指南

目录

[一、 物理层与通信协议基础 (底层时序)](#一、 物理层与通信协议基础 (底层时序))

[1. 硬件连接规则](#1. 硬件连接规则)

[2. 通信时序与数据帧 (以最常用的 10 位标准帧 8N1 为例)](#2. 通信时序与数据帧 (以最常用的 10 位标准帧 8N1 为例))

[二、 UART 底层硬件架构 (双缓冲机制)](#二、 UART 底层硬件架构 (双缓冲机制))

[1. 接收双缓冲:移位寄存器 & RDR (接收数据寄存器)](#1. 接收双缓冲:移位寄存器 & RDR (接收数据寄存器))

[2. 发送双缓冲:TDR (发送数据寄存器) & 移位寄存器](#2. 发送双缓冲:TDR (发送数据寄存器) & 移位寄存器)

[3. 波特率发生器 (Baud Rate Generator)](#3. 波特率发生器 (Baud Rate Generator))

[三、 底层硬件的四大核心中断机制](#三、 底层硬件的四大核心中断机制)

[四、 软件生态演进:标准库 vs HAL 库](#四、 软件生态演进:标准库 vs HAL 库)

[五、 终极奥义:HAL 库 API 与底层硬件中断的映射关系](#五、 终极奥义:HAL 库 API 与底层硬件中断的映射关系)

[1. 基础系列 HAL_UART_... (已知长度处理)](#1. 基础系列 HAL_UART_... (已知长度处理))

[2. 扩展系列 HAL_UARTEx_... (不定长数据处理)](#2. 扩展系列 HAL_UARTEx_... (不定长数据处理))

极简速记对照表


一、 物理层与通信协议基础 (底层时序)

串口(UART)是一种异步串行通信协议。它的根本在于**"双方约定相同的波特率,并用规定的速率去采样电平数据"**。

1. 硬件连接规则

  • 交叉连接: 设备 A 的 TX(发送数据线)连设备 B 的 RX(接收数据线),设备 A 的 RX 连设备 B 的 TX。

  • 必须共地 (GND): 串口是通过电压高低来判断 0 和 1 的。如果没有连接 GND 提供统一的电压参考零点,通信绝对会乱码或无法识别。

2. 通信时序与数据帧 (以最常用的 10 位标准帧 8N1 为例)

在总线空闲时,RX 和 TX 线的默认状态为高电平。发送一次常规数据需要 10 位(Bit):

  1. 起始位 (1位):把高电平拉低。 这是极其重要的一步!接收方检测到电平由高变低的"下降沿",才知道数据要来了,并开始按波特率计时。

  2. 数据位 (8位): 真正的有效数据。低电平代表 0,高电平代表 1。(注意:串口底层是低位 LSB 先发,高位 MSB 后发)

  3. 校验位 (可选): 通常不用(配置为 None)。

  4. 停止位 (1位):【🚨 核心要求】必须将电平拉高! 停止位必须是高电平,目的是强行让总线恢复到默认的高电平空闲状态,这样才能保证下一个起始位的"由高变低"能被成功检测到。


二、 UART 底层硬件架构 (双缓冲机制)

单片机内部到底长什么样?为什么会有"移位寄存器"和"数据寄存器"之分?其实串口内部采用的是**"双缓冲架构 (Double Buffer)"**。

1. 接收双缓冲:移位寄存器 & RDR (接收数据寄存器)

  • 接收移位寄存器: 这是一个在底层默默"接砖头"的临时工。外部 RX 线上的数据是一位一位(串行)进来的,移位寄存器就像一个抽屉,每来一个 Bit,它就把抽屉里的数据往左推一格,直到 8 个 Bit 全部收齐。

  • RDR (接收数据寄存器): 当移位寄存器凑齐 8 个 Bit 后,它会瞬间把这 8 个 Bit 并行(一次性) 倒进 RDR 寄存器中。此时触发 RXNE 中断,通知 CPU:"砖凑齐了,快拿走!"

  • 为什么搞双缓冲? 如果没有 RDR,CPU 必须在第 8 个 Bit 刚收完的一瞬间立刻把数据拿走,否则第 9 个 Bit 进来就会把数据覆盖。有了双缓冲,移位寄存器可以继续收下一个字节,CPU 只要在下一个字节收完之前,把 RDR 里的数据读走就行,大大降低了 CPU 的压力。

2. 发送双缓冲:TDR (发送数据寄存器) & 移位寄存器

  • 逻辑完全反过来:CPU 把一个字节写进 TDR。硬件会自动把 TDR 的数据倒入"发送移位寄存器"。

  • 移位寄存器接管后,按照波特率,一位一位地通过 TX 引脚"挤"出去。

3. 波特率发生器 (Baud Rate Generator)

它是串口的"心脏起搏器"。内部有一个分频器,把单片机的系统时钟(如 72MHz)分频成你需要的采样频率(如 115200 bps)。


三、 底层硬件的四大核心中断机制

串口内部就像一个流水线,四大状态都会产生硬件标志位(Flag)。必须满足条件:"硬件标志位产生 (Flag=1) + 软件开启中断允许 (IE=1) + NVIC 配置放行",CPU 才会真正跳入真正的中断函数。

中断类型 标志位 触发条件 底层白话解释
接收非空中断 RXNE 数据从移位寄存器转移到接收数据寄存器 (DR) 后触发。 "收到了 1 个完整字节,放在 DR 里了,CPU 快来拿走!"
发送为空中断 TXE CPU 将数据放入发送数据寄存器 (DR) 后,数据进入发送移位寄存器。此时 DR 被腾空触发。 "我手里的这块砖(DR)扔进流水线了,CPU 可以给我下一块砖了!"
发送完成中断 TC 不仅发送 DR 空了,连发送移位寄存器也空了(最后一个停止位彻底发完)。 "全部砖头都彻底从引脚上丢出去了,打完收工!"
总线空闲中断 IDLE 接收到字节后,后面连着 1 个完整字节的时间(10个Bit时长)RX线都是高电平。 "运砖车断档了,外面没动静了,这批货发完了!"

四、 软件生态演进:标准库 vs HAL 库

当硬件中断产生时,软件怎么处理?

  • 标准库 (手工小作坊): 所有硬件中断都会进入同一个入口函数 USARTx_IRQHandler。软件必须在里面自己写 if 判断if(USART_GetITStatus(...) != RESET)),去查看到底是谁触发的警报,并且最后还需要手动清除标志位

  • HAL 库 (现代化工厂): 我们只需要调用对应的 API。HAL 库底层替我们写好了那几百行的 if 判断和清除标志位代码,它判断完之后,会自动呼叫对应的"回调函数 (Callback)"交给我们处理数据。


五、 终极奥义:HAL 库 API 与底层硬件中断的映射关系

在 HAL 库中,表面上你只是调用了一个函数,但底层其实是开启了不同的硬件警报器。根据是否使用 Ex 扩展函数,底层的逻辑有天壤之别。

1. 基础系列 HAL_UART_... (已知长度处理)

这个系列处理的是死心眼的"定长"任务,它绝对不会去开启空闲中断 (IDLE)。

  • 纯中断接收 (HAL_UART_Receive_IT):

    • 底层开关: 开启 RXNEIE

    • 触发事件: 仅靠 RXNE 标志位。

    • 逻辑: 外部每发来 1 个字节,打断 1 次 CPU。搬走数据后计数器减 1。减到 0 时关掉 RXNEIE 并呼叫回调。

  • 纯中断发送 (HAL_UART_Transmit_IT):

    • 底层开关: 先开 TXEIE,后开 TCIE

    • 触发事件: 接力赛。先由 TXE 触发塞数据,最后一个字节离开引脚时由 TC 触发回调。

  • DMA 接收 (HAL_UART_Receive_DMA):

    • 底层开关: 开启 DMA 控制器中断 (TCIE, HTIE)。强制关闭串口 RXNEIE

    • 触发事件: 只有 DMA 的 TC (满载) 或 HT (过半) 能触发中断。串口本身装聋作哑。

2. 扩展系列 HAL_UARTEx_... (不定长数据处理)

这个系列(带有 ToIdle 字眼)是专门为了对付"不知道对方发多少"而生的,它的核心灵魂就是必定会开启串口的 IDLE 中断

  • 纯中断空闲接收 (HAL_UARTEx_ReceiveToIdle_IT):

    • 底层开关: RXNEIE + IDLEIE

    • 触发事件: RXNE 搬砖,IDLE 负责断流截断结算。混合双打。

  • DMA 空闲接收 (HAL_UARTEx_ReceiveToIdle_DMA) - 【终极神仙函数】:

    • 底层开关: DMA 控制器中断 (TCIE, HTIE) + 串口的 IDLEIE依然强制关闭 RXNEIE

    • 触发事件 (跨部门竞速赛):

      • 部门 A (DMA 控制器): 数据刚好塞满,触发 DMA 的 TC (或 HT 过半)。

      • 部门 B (串口门卫): 数据没塞满但中途断流了,触发 串口的 IDLE

    • 殊途同归: 无论哪个硬件标志位触发,HAL 库都会聪明的计算出真实的字节数 Size,并最终统一导向同一个回调函数 RxEventCallback

极简速记对照表

你调用的 HAL 库 API 数据搬运工 触发 CPU 中断的底层硬件标志 (Flag)
HAL_UART_Receive_IT CPU 亲力亲为 仅 RXNE (每字节 1 次)
HAL_UART_Receive_DMA DMA 硬件搬运 仅 DMA TC / HT (串口装聋作哑,容易死等)
HAL_UARTEx_ReceiveToIdle_IT CPU 亲力亲为 RXNE (每字节搬运) + IDLE (断流截断)
HAL_UARTEx_ReceiveToIdle_DMA DMA 硬件搬运 DMA TC / HT (满载保底) + 串口 IDLE (断流截断,工业首选)
相关推荐
ILYT NCTR2 小时前
SocketTool、串口调试助手、MQTT中间件基础
单片机·嵌入式硬件·中间件
LCMICRO-133108477462 小时前
长芯微LCMDC8685完全P2P替代ADS8685,16位模数转换器(ADC)
单片机·嵌入式硬件·fpga开发·硬件工程·dsp开发·模数转换器adc
进击的小头2 小时前
第16篇:嵌入式工业通信外设:CAN_CAN FD总线接口原理与组网应用
单片机·嵌入式硬件
szxinmai主板定制专家2 小时前
基于ARM+FPGA高性能MPSOC 多轴伺服设计方案
arm开发·人工智能·嵌入式硬件·fpga开发·架构
WeeJot嵌入式2 小时前
【IIC】IIC通信与温湿度传感器AHT20(DHT20)
stm32·单片机·嵌入式硬件·嵌入式·iic
WeeJot嵌入式3 小时前
【串口】蓝牙模块与简易数据包解析
stm32·单片机·嵌入式硬件·蓝牙
国科安芯3 小时前
抗辐照DCDC电源模块在商业卫星通信载荷中的应用
网络·人工智能·单片机·嵌入式硬件
m0_377108143 小时前
物理day4-22
单片机
nuoxin1143 小时前
CYUSB4024-FCAXI 是一款USB 20Gbps 控制器-富利威
网络·人工智能·嵌入式硬件·fpga开发·dsp开发