当前位置: 首页 > news >正文

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

目录

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

1. 硬件连接规则

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

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

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

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

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

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

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

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

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

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 快来拿走!”
发送为空中断TXECPU 将数据放入发送数据寄存器 (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_ITCPU 亲力亲为仅 RXNE(每字节 1 次)
HAL_UART_Receive_DMADMA 硬件搬运仅 DMA TC / HT(串口装聋作哑,容易死等)
HAL_UARTEx_ReceiveToIdle_ITCPU 亲力亲为RXNE(每字节搬运) +IDLE(断流截断)
HAL_UARTEx_ReceiveToIdle_DMADMA 硬件搬运DMA TC / HT(满载保底) +串口 IDLE(断流截断,工业首选)
http://www.jsqmd.com/news/684102/

相关文章:

  • .NET命名之谜:它与C#纠缠年的关系揭秘
  • CSS如何处理旧版浏览器的浮动兼容性_利用zoom-1触发hasLayout清除css浮动
  • ReadCat技术架构深度解析:模块化设计下的现代桌面阅读器实现
  • 从OOSEM到MagicGrid:一文理清主流MBSE方法论,帮你找到最适合自己项目的建模路线图
  • 别再死记硬背快捷键了!用这5个Blender 4.0实战案例,让你彻底理解建模逻辑
  • 拓展中国剩余定理
  • 【NLP实践指南】从BERT的last_hidden_state到pooler_output:如何为不同任务精准选择语义向量
  • 2025届最火的六大AI写作方案推荐榜单
  • 别再手动改Hosts了!用SwitchHosts一键管理多环境,开发效率翻倍(附Git同步配置)
  • 从GitHub到百度云:手把手教你备份和整理吴恩达机器学习全套资源(笔记+代码+视频)
  • 从Slab到内存池:深入拆解Linux内核如何高效管理‘碎片化’小内存(以task_struct为例)
  • 别再只会写黑框框了!用EGE给C语言课设做个带登录界面的图形化系统(附完整源码)
  • 从挂科边缘到高分飘过:我的华科矩阵论自救笔记(附GitHub超全资料)
  • 2026年小红书被朱雀AIGC检测?去i迹+嘎嘎降3步降到15%
  • 从游戏碰撞检测到地图围栏:用Shapely玩转Python几何运算的3个实战项目
  • 别再手动对齐了!用Creo的骨架模型做装配,效率提升不止一点点
  • git提交总结
  • 基于yolov5-v11和deepsort的行人跌倒检测系统 GUI部分使用pyqt5,YOLOv5-v11 + DeepSORT + PyQt5跌倒检测识别系统
  • .NET 11原生AI推理性能翻倍实录:绕开5大Runtime陷阱、3类Tensor内存泄漏与2种JIT编译失效场景
  • 3步实战指南:从零到精通Tesseract OCR识别技术
  • 苹果高层变动:库克卸任 CEO 转任董事长,功绩与争议并存
  • Transformer跨界搞目标检测?拆解Grounding DINO里那些让模型‘听懂人话’的关键模块
  • CN3702 5A 双节锂电池充电管理集成电路
  • 一个让我彻底放弃传统IoT的“AI老六”
  • claude code 安装及 国内大模型接入指南
  • CH34X-MPHSI Master总线扩展实战:SPI设备即插即用与驱动无缝迁移
  • 每日一Go-55、分布式 ID 生成(雪花算法 / Segment / Redis / DB)
  • 换了Homebrew国内源还是装不上Node?可能是你的缓存和源配置在‘打架’
  • 零基础学习C语言:从入门到精通的实用指南
  • 三步解锁QQ音乐加密文件:macOS用户的音频自由指南