前言:在学习 STM32 的过程中,串口通信(USART) 是最常用、也是最基础的外设之一。
它不仅可以用来输出调试信息,还常被用于与其他模块(如 GPS、蓝牙、WiFi、传感器等)之间进行通信。上一篇文章我们介绍了 STM32 USART 的发送功能,本文将重点讲解 USART 的接收机制 ------ 包括初始化配置、接收中断、数据读取与显示。同时,我们还将通过 OLED 显示模块来观察接收到的数据,从而直观了解整个数据流过程。相关发送的博客二十九、STM32的USART (串口发送)
目录
[一、USART 接收原理简介](#一、USART 接收原理简介)
[二、USART 接收程序结构分析](#二、USART 接收程序结构分析)
[三、USART 初始化配置](#三、USART 初始化配置)
[四、SART 接收中断服务函数](#四、SART 接收中断服务函数)
一、USART 接收原理简介
USART(Universal Synchronous/Asynchronous Receiver/Transmitter,通用同步/异步收发器)是一种通用的串行通信接口。
在异步模式下,它主要依靠起始位和停止位来同步数据帧,而接收端通过中断机制检测并读取接收到的数据。
USART 的接收流程可以概括为以下几步:
-
当数据帧到达时,USART 硬件自动检测起始位;
-
数据按位采样后存入接收数据寄存器;
-
RXNE(接收缓冲非空)标志位置 1;
-
若使能了中断,CPU 会自动跳转到中断函数中;
-
用户代码读取寄存器数据;
-
读取后 RXNE 自动清零,等待下一次接收。
二、USART 接收程序结构分析
我们在本例中使用 USART1 进行通信。
引脚配置如下:

三、USART 初始化配置
void Serial_Init(void)
{
/* 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* 配置 TX 引脚 PA9 为复用推挽输出 */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 配置 RX 引脚 PA10 为上拉输入 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* USART 参数配置 */
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600; // 波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; // 启用收发模式
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &USART_InitStructure);
/* 开启接收中断 */
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
/* NVIC 配置 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* 使能 USART1 */
USART_Cmd(USART1, ENABLE);
}
这部分代码完成了:
✅ 时钟开启
✅ GPIO 配置(PA9 / PA10)
✅ 串口通信参数初始化
✅ 开启 RXNE 接收中断
✅ 配置 NVIC 优先级与中断入口
四、SART 接收中断服务函数
当串口接收到数据后,RXNE 标志位置 1,并自动触发中断。
以下是中断函数:
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET) // 判断是否为接收中断
{
Serial_RxData = USART_ReceiveData(USART1); // 读取接收数据
Serial_RxFlag = 1; // 设置标志位
USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清除中断标志位
}
}
注意:
-
读取
USART_ReceiveData()后,RXNE 位会自动清零。 -
为了防止遗漏,也可以手动调用
USART_ClearITPendingBit()清除标志。 -
中断函数名称必须与启动文件定义的保持一致,否则不会被调用。
五、接收标志位与数据读取函数
为了让主函数方便使用,我们定义了两个接口函数:
uint8_t Serial_GetRxFlag(void)
{
if (Serial_RxFlag == 1)
{
Serial_RxFlag = 0;
return 1;
}
return 0;
}
uint8_t Serial_GetRxData(void)
{
return Serial_RxData;
}
这样主循环中就可以用"轮询方式"来检测是否收到新数据。
六、主函数与数据回显
主函数的逻辑非常清晰:
1️⃣ 等待串口接收标志位;
2️⃣ 读取接收数据;
3️⃣ 通过串口将数据回传(即回显测试);
4️⃣ 通过 OLED 显示接收的内容。
int main(void)
{
OLED_Init(); // 初始化 OLED
OLED_ShowString(1, 1, "RxData:");
Serial_Init(); // 初始化串口
while (1)
{
if (Serial_GetRxFlag() == 1) // 检测是否接收到数据
{
RxData = Serial_GetRxData(); // 读取接收数据
Serial_SendByte(RxData); // 将数据回显
OLED_ShowHexNum(1, 8, RxData, 2); // 显示数据的十六进制值
}
}
}
七、运行结果与测试现象
-
打开串口调试助手,设置波特率为 9600。
-
向 STM32 发送任意字符(例如字母 A)。
-
OLED 显示屏上将显示接收到的数据(十六进制形式,如
0x41)。 -
串口助手也会收到 STM32 回传的相同数据。
八、总结
通过本次实验,我们实现了 STM32C8T6 的 USART 接收功能,并通过中断机制实现了高效、可靠的数据获取。
🔹 重点知识回顾:
-
USART 的接收由硬件自动检测起始位;
-
RXNE 标志位指示接收缓冲区状态;
-
中断方式比轮询方式更高效;
-
通过标志位机制实现主循环与中断的解耦;
-
接收到的数据可用于显示、处理或回传测试。