STM32 USART 详解(四):数据帧及标志位的收发机制与寄存器深度剖析
2026/9/11 22:06:51 网站建设 项目流程

目录

  • 前言
  • 一、USART模块地址空间
    • 1.1 STM32统一编址机制
    • 1.2 USART1地址范围详解
    • 1.3 各串口模块地址清单
  • 二、USART寄存器结构
    • 2.1 寄存器列表与偏移量
    • 2.2 寄存器权限标识说明
  • 三、数据寄存器 USART_DR
    • 3.1 TDR与RDR的双重角色
    • 3.2 DR寄存器的位结构
  • 四、数据帧格式
    • 4.1 数据帧结构组成
    • 4.2 以发送0x55为例的波形分析
    • 4.3 起始位与停止位的电平本质
  • 五、USART发送机制
    • 5.1 从TDR到发送移位寄存器的数据流转
    • 5.2 数据覆盖问题——为什么不能盲目连续写入
    • 5.3 TXE与TC——衡量发送状态的两个核心标志位
      • 5.3.1 TXE(Transmit Data Register Empty,发送数据寄存器空)
      • 5.3.2 TC(Transmission Complete,发送完成)
      • 5.3.3 TXE与TC的区别
    • 5.4 USART_SR状态寄存器全景
  • 六、USART带标志位的数据发送原理
    • 6.1 用户视角:什么时候可以写入数据
    • 6.2 USART硬件视角:TXE标志的翻转时机
  • 七、三字节完整发送流程剖析(0x00 → 0xFF → 0x55)
    • 7.1 第一阶段:发送 0x00
    • 7.2 第二阶段:发送 0xFF
    • 7.3 第三阶段:发送 0x55
    • 7.4 发送完毕:TC标志位的翻转
  • 八、阻塞式发送模式
  • 九、时钟域的并行操作
  • 十、USART 详细接收过程
    • 10.1 数据帧格式回顾
    • 10.2 接收过程的逐步拆解
      • 10.2.1 第一阶段:检测起始位
      • 10.2.2 第二阶段:逐位接收数据位
      • 10.2.3 第三阶段:接收校验位
      • 10.2.4 第四阶段:检测停止位
      • 10.2.5 第五阶段:校验与数据平移
    • 10.3 RXNE 标志位——接收就绪的信号
      • 10.3.1 RXNE 位的定义
      • 10.3.2 RXNE 的硬件置位机制
      • 10.3.3 RXNE 的清除机制
    • 10.4 阻塞式读取机制
      • 10.4.1 轮询检测 RXNE
      • 10.4.2 形象比喻
      • 10.4.3 责任边界
      • 10.4.4 读取后自动清零
    • 10.5 连续接收的时序关系
  • 结语




🎬 云泽Q:个人主页

🔥 专栏传送入口: 《C语言》《数据结构》《C++》《Linux》《蓝桥杯系列》《笔试算法》《AI赋能》《STM32》《Python》
⛺️遇见安然遇见你,不负代码不负卿~

前言

大家好啊,我是云泽Q,欢迎阅读我的文章,一名热爱计算机技术的在校大学生,喜欢在课余时间做一些计算机技术的总结性文章,希望我的文章能为你解答困惑~

一、USART模块地址空间

1.1 STM32统一编址机制

在STM32F103ZET6这款MCU内部,所有片上外设——包括SRAM、Flash以及各类外设模块——都处于CPU的统一编址空间之下,完成地址映射。换句话说,每一个外设、每一个寄存器,最终都对应着一个明确的物理地址。CPU通过对这些物理地址的读写操作,来实现对外设的控制和数据交互。

具体到USART模块,STM32F103ZET6内部总共包含了5个串口接口:USART1、USART2、USART3、UART4、UART5。每一个串口都是一个独立的硬件单元,拥有自己专属的地址空间。只要搞清楚其中一个串口的硬件结构和寄存器组,其余所有串口的原理完全一致,可以直接举一反三。

1.2 USART1地址范围详解

以USART1为例,它的物理地址范围是:

0x4001 3800 ~ 0x4001 3BFF

这个地址空间的大小可以通过公式计算:

结束地址 - 起始地址 + 1 = 0x4001 3BFF - 0x4001 3800 + 1 = 0x3FF + 1 = 0x400(十六进制)

将0x400转换为十进制:1024字节,即1KB

也就是说,CPU内核为USART1分配了1KB的地址空间。但实际使用中,只有最开头的很少一部分地址被真正使用到了,后续的大部分地址是保留的,访问它们可能产生不可预知的行为。

USART1中一共有7个寄存器,每一个寄存器都有一个偏移量地址。访问任何一个寄存器的方式都是:

USART1基地址(0x4001 3800) + 寄存器偏移量

1.3 各串口模块地址清单

外设所在总线起始地址结束地址地址空间大小类型
USART1APB20x4001 38000x4001 3BFF1 KB高级同步/异步串行接口
USART2APB10x4000 44000x4000 47FF1 KB通用同步/异步串行接口
USART3APB10x4000 48000x4000 4BFF1 KB通用同步/异步串行接口
UART4APB10x4000 4C000x4000 4FFF1 KB通用异步串行接口
UART5APB10x4000 50000x4000 53FF1 KB通用异步串行接口

可以看到,USART1挂载在APB2总线上,而其余串口均挂载在APB1总线上。这也说明USART1的性能和时钟频率与其他串口有所不同。

二、USART寄存器结构

2.1 寄存器列表与偏移量

USART1的7个寄存器及其偏移量如下:

寄存器偏移量(Offset)地址计算过程最终地址
USART_SR0x000x4001 3800 + 0x000x4001 3800
USART_DR0x040x4001 3800 + 0x040x4001 3804
USART_BRR0x080x4001 3800 + 0x080x4001 3808
USART_CR10x0C0x4001 3800 + 0x0C0x4001 380C
USART_CR20x100x4001 3800 + 0x100x4001 3810
USART_CR30x140x4001 3800 + 0x140x4001 3814
USART_GTPR0x180x4001 3800 + 0x180x4001 3818

这里我们重点关注前几个核心寄存器:

  • USART_SR(状态寄存器):偏移量0x00,用于存放各种状态标志位,包括我们后面重点讲解的TXE和TC。
  • USART_DR(数据寄存器):偏移量0x04,是发送和接收数据的核心寄存器。

2.2 寄存器权限标识说明

在参考手册的寄存器位描述中,你会看到类似rcw0r这样的标识,这些代表了每一位的读写权限:

  • r(Read Only,只读):该位只能读取,不能写入。从编程角度,你可以直接读取寄存器的值来获取状态。
  • rc(Read Clear,读后清零):该标志位由硬件自动置位,当你在软件中读取该寄存器(或对应位)后,硬件会自动将该位清零。这是一个典型的"读即清"机制。
  • w0(Write 0 to Clear,写0清零):该位可以通过软件写0来清零。写入1通常不影响该位的状态。

这些权限标识反映了硬件对各个标志位的管理方式。很多情况下,标准库或HAL库已经帮我们处理了这些底层的读写操作,不需要我们手动去操作。但了解这些底层机制,有助于在遇到异常时进行深度调试。

三、数据寄存器 USART_DR

3.1 TDR与RDR的双重角色

USART_DR是串口通信中最核心的寄存器之一,它的偏移量为0x04,对于USART1来说,其物理地址为0x4001 3804

从数据手册的描述来看,USART_DR被标注为一个寄存器,但实际上它由两个逻辑寄存器组成:

  • TDR(Transmit Data Register,发送数据寄存器):用于发送数据。当CPU向USART_DR写入数据时,数据被写入TDR。
  • RDR(Receive Data Register,接收数据寄存器):用于接收数据。当CPU从USART_DR读取数据时,数据来自RDR。

TDR和RDR共享同一个物理地址(0x4001 3804),通过总线控制信号中的读写方向来区分:

  • 写操作→ 访问TDR(发送方向)
  • 读操作→ 访问RDR(接收方向)

TDR寄存器提供了内部总线(APBx)和输出移位寄存器之间的并行接口;RDR寄存器提供了输入移位寄存器和内部总线之间的并行接口。

3.2 DR寄存器的位结构

USART_DR是一个32位寄存器,但实际只使用了低9位:

位段名称说明
位31:9保留位硬件强制为0
位8:0DR[8:0]数据值(Data value),共9位

DR[8:0]共9位,意味着USART最多支持9位数据的传输。

  • 如果配置为9位数据位,则无法启用奇偶校验功能。
  • 工程中更常见的配置是8位数据 + 1位奇偶校验(如8N1、8E1、8O1)。

当使能校验位(USART_CR1中PCE位被置位)进行发送时,写到MSB的值(根据数据长度不同,MSB是第7位或第8位)会被后来的校验位所取代。也就是说,硬件会自动用计算出的校验位覆盖最高数据位,用户无需手动计算校验值。

四、数据帧格式

4.1 数据帧结构组成

串口通信的数据是以**帧(Frame)**为单位进行传输的。一个完整的数据帧由以下部分组成:

[起始位] + [数据位] + [校验位(可选)] + [停止位]

以最常见的配置为例:

  • 起始位:1位,固定为低电平(0),用于通知接收方"数据开始传输"
  • 数据位:8位(或9位),实际要传输的数据,LSB(最低有效位)先发
  • 校验位:1位(奇校验或偶校验),由硬件自动生成
  • 停止位:1位(或1.5位、2位),固定为高电平(1),用于标识一帧结束


所以一帧完整的帧包含:1 + 8 + 1 + 1 =11位

4.2 以发送0x55为例的波形分析

以发送数据0x55为例来直观理解数据帧的传输过程:

0x55 的二进制 = 0101 0101

由于串口通信是LSB先发(最低有效位优先),所以实际发送顺序为:

起始位 → 数据位(LSB→MSB) → 校验位 → 停止位 0 → 1 0 1 0 1 0 1 0 → 奇校验位 → 1

完整帧为:0(起始)+ 10101010(数据,LSB先发)+ 1(奇校验)+ 1(停止)= 11位

波形图上各阶段的含义:

阶段名称电平说明
空闲状态高电平无数据传输时,TX线保持高电平
起始位低电平拉低电平,触发接收方开始采样
数据位高低交替8位数据逐位发送,LSB先发
校验位由数据决定奇校验位,硬件自动填充
停止位高电平拉高电平,标识一帧结束,回到空闲状态

4.3 起始位与停止位的电平本质

起始位和停止位虽然可以用逻辑0和逻辑1来理解,但更好的理解方式是从电平角度

  • 起始位:本质上就是USART硬件发现"有数据要发送"时,主动拉低TX引脚的电平,形成低电平触发信号,通知接收端"准备接收数据"。
  • 停止位:本质上就是USART硬件发现"数据发送完成"时,主动拉高TX引脚的电平,形成高电平恢复信号,表示"这一帧结束了,回到空闲状态"。

接收端收到的是一串高低电平交替的方波,最终形成的波形就是我们在示波器上看到的样子。起始位可以理解为逻辑0,但更好的方式是理解成低电平;停止位可以理解为逻辑1,但更好的方式是理解成高电平

五、USART发送机制

5.1 从TDR到发送移位寄存器的数据流转

整个发送过程涉及两个关键的寄存器层次:

CPU(通过APB总线)→ 写入 → TDR(发送数据寄存器)→ 硬件转移 → 发送移位寄存器 → 逐位输出到TX引脚

具体流程如下:

  1. 用户程序将要发送的数据写入USART_DR(实际写入TDR)。
  2. USART硬件检测到TDR中有数据后,将TDR中的数据一次性并行转移到发送移位寄存器中。
  3. 发送移位寄存器在USART时钟驱动下,将数据逐位串行输出到TX引脚,LSB先发。
  4. 硬件自动在数据帧前后添加起始位和停止位,并根据配置自动填充校验位。

注意:发送移位寄存器对用户是不可见的,用户只能通过TDR来操作发送数据。

5.2 数据覆盖问题——为什么不能盲目连续写入

假设USART底层正在发送数据,发送移位寄存器中还有数据未发完。此时如果用户再次向TDR写入新数据,会发生什么?

while(cnt){TDR=cnt;cnt--;}

如果第一次写入时USART正在忙,数据暂存在TDR中等待转移到移位寄存器。如果在USART还没完成转移和发送之前,用户第二次又往TDR写入数据,那么新数据会直接覆盖TDR中尚未发送的旧数据,导致数据丢失。

这就好比你一边在说话,别人一边往你嘴里塞新的台词——你根本来不及把之前的话说完。

因此,在发送数据之前,必须确认TDR是否为空,即上一次的数据是否已经被转移到移位寄存器中。这正是TXE标志位存在的意义。

5.3 TXE与TC——衡量发送状态的两个核心标志位

USART_SR状态寄存器中有两个极其重要的标志位,专门用来衡量发送过程的状态:

5.3.1 TXE(Transmit Data Register Empty,发送数据寄存器空)

  • 位置:USART_SR的位7
  • 含义:当TDR中的数据被硬件转移到发送移位寄存器后,该位被硬件置1。
  • 取值说明
    • 0:数据还没有被转移到移位寄存器,TDR非空,此时不能写入新数据。
    • 1:数据已经被转移到移位寄存器,TDR已空,可以写入下一帧数据。
  • 清零方式:对USART_DR进行写操作时,该位自动清零(因为写入新数据后TDR不再为空)。
  • 应用场景:主要用于单缓冲器传输中,判断是否可以写入下一字节数据。

5.3.2 TC(Transmission Complete,发送完成)

  • 位置:USART_SR的位6
  • 含义:当包含有数据的一帧发送完成后,并且TXE=1时,由硬件将该位置1。
  • 取值说明
    • 0:发送还未完成。
    • 1:发送已完成,整个数据帧(包括停止位)已全部从TX引脚发出。
  • 清零方式
    • 软件序列清除:先读USART_SR,然后写入USART_DR。
    • 或者直接写入’0’来清除(仅在多缓冲器通讯中推荐)。
  • 应用场景:用于判断整帧数据是否彻底发送完毕

5.3.3 TXE与TC的区别

这两个标志位经常被混淆,它们的本质区别在于衡量的阶段不同

标志位衡量的是什么何时置1
TXETDR寄存器是否为空数据从TDR转移到移位寄存器后立即置1
TC整帧数据是否发送完毕移位寄存器中最后一位(含停止位)发完后置1

简单来说:

  • TXE=1意味着:TDR空了,你可以写下一字节了,但当前这一帧可能还在移位寄存器中慢慢发。
  • TC=1意味着:不仅TDR空了,移位寄存器也空了,整个数据帧已经全部从TX引脚发出去了。

5.4 USART_SR状态寄存器全景

USART_SR(状态寄存器)位于偏移量0x00处,复位值为0x00C0。其关键位段如下:

名称权限说明
位7TXEr发送数据寄存器空
位6TCrc w0发送完成
位5RXNErc w0读数据寄存器非空(接收数据就绪)
位4IDLErc w0空闲线检测
位3OREr溢出错误
位2NEr噪声错误标志
位1FEr帧错误
位0PEr校验错误

其中我们当前阶段重点关注的是**TXE(位7)TC(位6)**这两个发送相关的标志位。后续进入接收阶段后,RXNE(位5)将成为核心关注点。

六、USART带标志位的数据发送原理

当我们把两个核心标志位——TXE和TC——引入到USART的发送流程中后,串口发送就进入了真正意义上的实战阶段。在用户代码层面进行数据帧发送时,真实情况下的每一次发送都是要携带标志位来判断状态的。

我们要发送三个字节的数据,分别是0x000xFF0x55。这一次不只是一个数据,而是连续三个。数据帧的格式设定为:1位起始位 + 8位数据位 + 1位奇校验位 + 1位停止位,总共11位。这个帧格式是我们之前一直沿用的,此处不再赘述。

6.1 用户视角:什么时候可以写入数据

站在用户的角度,理解TXE和TC的状态变化逻辑至关重要:

  • TXE == 1时,说明TDR是空的。此时如果用户还有数据要发送,就可以放心地继续写入下一个字节。
  • 如果用户的数据已经全部写完了,那就什么都不用做,静等USART硬件把剩余数据发完。当TC变成1时,意味着TXE == 1 && TC == 1,表示本轮数据全部发送完毕。
  • 如果数据没发完,只要TXE == 1,用户就可以继续往TDR里写新数据。

用户判断逻辑就是:TXE == 1 && 自己还有数据要发,那么就继续发送。



6.2 USART硬件视角:TXE标志的翻转时机

从USART硬件模块的角度来看,它的运作逻辑是这样的:

  1. USART必须先把当前移位寄存器里的数据全部串行发送完毕。
  2. 发送完成后,USART才会把TDR寄存器中的数据平移到发送移位寄存器。
  3. 只有TDR中的数据成功平移到发送移位寄存器之后,USART才会将TXE设置为1,表示TDR已空,允许用户再次写入。

这就是TXE的本质——USART硬件模块用来指导用户写入数据的指挥棒。它告诉用户:现在TDR空了,你可以写了;或者TDR还被占着,你必须等。

如果用户无视TXE标志位,在TXE == 0(TDR不空)时强行写入数据,就会导致自己覆盖了自己的数据。这时候锅要用户自己背,因为USART已经通过TXE标志告诉你TDR不为空了,你还要往里写。

所以,用户要写TDR,必须先对TXE进行判定,只有TXE == 1,用户才能再写入。

七、三字节完整发送流程剖析(0x00 → 0xFF → 0x55)

下面我们以发送0x000xFF0x55这三个字节为例,从时序角度逐步拆解整个发送过程。

7.1 第一阶段:发送 0x00

初始状态下,TDR为空,TXE = 1,TC = 1。

用户将第一个数据0x00写入TDR。此时:

  • TDR被占用,TXE被USART自动设置为0。
  • TC也被设置为0(因为发送尚未完成)。
  • USART硬件自动将TDR中的数据(1-0-0-0-0-0-0-0-0,含起始位和校验位)平移到发送移位寄存器。
  • TDR重新变为空,TXE恢复为1。
  • 发送移位寄存器开始按位串行输出数据到TX引脚。

此时TC仍为0,因为移位寄存器中还有数据正在发送。

7.2 第二阶段:发送 0xFF

USART硬件在自身时钟驱动下,继续从移位寄存器逐位输出0x00的数据帧。

同时,由于上一阶段TDR已经变空(TXE = 1),用户代码检测到TXE == 1后,将第二个数据0xFF写入TDR。此时:

  • TDR再次被占用,TXE被设置为0。
  • 注意:如果此时USART硬件中上一次0x00的数据还没有从移位寄存器发送完毕,那么TDR内部的0xFF就无法被平移到移位寄存器。
  • 因此TDR一直被占用,TXE保持为0。

用户必须等待TXE变回1,才能写入下一个数据。

当USART把0x00的所有位(11位)全部发送完毕后,硬件会将TDR中的0xFF平移到移位寄存器。平移完成后:

  • TDR重新变空,TXE被USART设置为1。
  • 移位寄存器开始串行输出0xFF(加上奇校验位后为1-1-1-1-1-1-1-1-1)。

7.3 第三阶段:发送 0x55

此时TXE = 1,用户检测到后,将第三个数据0x55写入TDR。

  • TDR被占用,TXE被设置为0。
  • USART继续从移位寄存器输出0xFF的数据帧。

0xFF的数据帧全部输出完毕后:

  • USART将TDR中的0x55平移到移位寄存器。
  • TDR变空,TXE被设置为1。
  • 移位寄存器开始输出0x55的数据帧。

此时用户已经没有更多数据要发送了。TDR保持为空(TXE = 1)。

7.4 发送完毕:TC标志位的翻转

当最后一个数据0x55的所有位也从移位寄存器全部串行输出到TX引脚后:

  • TDR为空(TXE = 1)
  • 移位寄存器也为空

两个条件同时满足,USART硬件将TC标志位置为1,宣告本次多字节数据发送全部完成。

此时TXE == 1 && TC == 1,整个发送流程结束。

八、阻塞式发送模式

在实际编程中,用户发送数据时必须对TXE标志位进行检测:

  • 如果TXE == 0,表示TDR中的数据还没有被平移到发送移位寄存器(TDR被占用)。此时用户必须阻塞在检测TXE标志位的位置进行等待,直到TXE变为1。

这种模式的写入方式就叫做阻塞式发送

在时序图上可以清晰地看到:

  • 数据寄存器TDR中依次装入数据1、数据2、数据3。
  • 每当一个数据从TDR平移到发送移位寄存器时,TXE标志从低电平跳变为高电平(标记为时刻①、②)。
  • 用户只有在TXE变高的时刻才能写入下一个数据。
  • 当最后一个数据全部发送完毕,TDR和发送移位寄存器都为空时,TC标志被置为1(标记为时刻③)。

所以,如果使用阻塞模式进行数据发送(一个或多个数据之后),要知道USART是否彻底把数据全部发送出去了,就看TC标志位。当TC == 1时,表示要发送的数据已全部发送完成。

九、时钟域的并行操作

需要特别注意的是,CPU和USART模块是在各自的时钟域下独立运行的:

  • CPU通过APBx总线时钟向TDR写入数据。
  • USART模块通过自身的波特率时钟从移位寄存器逐位串行输出数据。

这意味着,在时间维度上,用户向TDR写入下一个数据USART从移位寄存器发送当前数据是可以并行进行的。只要TDR是空的(TXE == 1),用户就可以提前把下一个数据写好放进去,等USART发完当前数据后,硬件会自动把TDR中的新数据搬运到移位寄存器继续发送。

这种硬件层面的自动平移机制,使得串口发送在效率上远高于CPU逐位模拟的方式。

十、USART 详细接收过程

前面我们完成了 STM32 USART 发送的详细过程,数据帧格式和标志位都已经搞定了。接下来进入下一个话题——USART 详细的接收过程

之前我们聊接收的时候,只是站在 8 位数据位的角度,并没有谈任何数据帧格式。所以这一次,我们要带着完整的帧格式来理解接收的全貌。

10.1 数据帧格式回顾

以发送端发送0x55为例,对应的二进制为0101 0101

我们约定的帧格式为:

组成部分位数说明
起始位1 位低电平(拉低),标记一帧数据的开始
数据位8 位实际有效数据
校验位1 位奇校验位
停止位1 位高电平(拉高),标记一帧数据的结束

总共 11 位比特位构成一帧完整的数据。

需要特别注意的是:发送端是从低位向高位逐位发送的0x55的二进制0101 0101,我们人眼阅读时是从高位到低位读的,但在物理线路上,发送端先发最低位的1,再发010……依此类推。所以线路上实际传输的比特流顺序为:

起始位(0) → 1 → 0 → 1 → 0 → 1 → 0 → 1 → 0 → 校验位(1) → 停止位(1)

接收端按这个顺序依次接收到自己的接收移位寄存器中。

10.2 接收过程的逐步拆解

10.2.1 第一阶段:检测起始位

接收端的 RX 引脚平时处于空闲的高电平状态。当接收控制器检测到一个拉低的电平(低电平)时,就知道对方开始发送数据了。

这个低电平仅仅用于 USART 内部判断"对方开始发了",不需要保存,更不需要被用户读取。起始位由硬件自动识别和处理。

收到这个拉低的电平后,接收移位寄存器准备好接收对面的数据,第一个进入接收移位寄存器的就是起始位。

10.2.2 第二阶段:逐位接收数据位

起始位之后,发送端开始逐位发送 8 位数据。接收端按照约定的波特率(时钟节拍),一位一位地把数据从 RX 引脚读入接收移位寄存器中。

0x55为例,实际进入接收移位寄存器的顺序为:

第1位进入:1 第2位进入:0 第3位进入:1 第4位进入:0 第5位进入:1 第6位进入:0 第7位进入:1 第8位进入:0



数据在接收移位寄存器中逐位右移填充,最终填满 8 个有效数据位。

10.2.3 第三阶段:接收校验位

8 位数据位之后,接下来进入的是 1 位校验位。在我们的奇校验配置下,0x55的二进制0101 0101中"1"的个数为 4 个(偶数),为了满足奇校验(总"1"个数为奇数),校验位为1

这个校验位同样被接收移位寄存器接收进来。

10.2.4 第四阶段:检测停止位

在收到约定的 9 位数据(8 位数据位 + 1 位校验位)之后,接收端继续检测线路电平。当读到拉高的电平时,就说明对方发完了,这就是停止位。

这个高电平同样仅仅是 USART 内部判断"对方发完了"的信号,不需要保存,更不需要被用户读取。停止位由硬件自动识别。

10.2.5 第五阶段:校验与数据平移

当 11 位完整帧全部接收完毕后,USART 模块自己进行校验:

  • 校验通过 → 有效数据(8 位)从接收移位寄存器平移到接收数据寄存器(RDR)。
  • 校验不通过 → 数据无效,可能触发错误标志位。

在这个过程中,起始位和停止位已经被硬件自动丢弃,它们只起到帧边界的标记作用,不会进入 RDR。

10.3 RXNE 标志位——接收就绪的信号

数据从接收移位寄存器平移到 RDR 的过程中,状态寄存器(USART_SR)中的RXNE 位会被硬件自动置 1。

10.3.1 RXNE 位的定义

RXNE 全称为Read Data Register Not Empty(读数据寄存器非空),位于 USART_SR 状态寄存器的位 5

位编号名称含义
位 5RXNE读数据寄存器非空
  • RXNE = 0:数据没有收到,RDR 为空,不可读取。
  • RXNE = 1:收到数据,RDR 非空,可以读出。

10.3.2 RXNE 的硬件置位机制

当 RDR 移位寄存器中的数据被转移到 USART_DR 寄存器中时,RXNE 位被硬件自动置位

如果 USART_CR1 寄存器中的 RXNEIE(接收中断使能位)为 1,则同时会产生中断。

10.3.3 RXNE 的清除机制

  • 正常读取清除:对 USART_DR(即 RDR)执行读操作,RXNE 位会被硬件自动清零。
  • 手动清除:RXNE 位也可以通过写入 0 来清除,但只有在多缓存通讯中才推荐这种清除方式。

10.4 阻塞式读取机制

有了 RXNE 标志位之后,用户就可以安全地读取数据了。具体做法是:

10.4.1 轮询检测 RXNE

在读取 RDR 之前,必须检测 RXNE 标志位:

while((USART_SR&0x0020)==0);// 轮询等待 RXNE 置 1// RXNE 为 1 后,安全读取数据uint8_treceived_data=USART_DR;// 读取数据,同时硬件清零 RXNE

标志位为 0 表示没有数据,程序通过while循环不断轮询检测。只要标志位一直为 0,程序就卡在那里等待

10.4.2 形象比喻

这个等待过程就像去食堂打饭:阿姨还没把饭菜端上来的时候,你只能站在点菜的位置上等待;阿姨把菜放上来了(RXNE 变 1),你这个时候才能拿到菜。

10.4.3 责任边界

这种机制明确了硬件和软件之间的责任边界:

  • USART 模块的责任:负责接收数据、校验数据、将有效数据放入 RDR,并置位 RXNE 通知用户"数据准备好了"。
  • 用户的责任:在 RXNE 置 1 之后去读取数据。只要标志位为 1,用户读数据读出错了就和 USART 模块没关系了——“我把我该做的工作做了,要后面读数据出错,这个锅我不背。”

10.4.4 读取后自动清零

只要用户把数据读走了,RXNE 标志位就会被 USART 硬件自动清零,回到 0 状态,准备接收下一帧数据。

10.5 连续接收的时序关系

当连续接收多帧数据时,时序关系如下:

每一帧数据接收完成并校验通过后,RXNE 被置 1(图中①②③标记处),用户读取后 RXNE 自动清零,等待下一帧。


结语

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询