STM32F405 USART3中断中RXNE标志无故自动清除问题求助
STM32F405 USART3中断接收异常:RXNE/IDLE标志自动清除
问题现象
在CubeIDE中调试STM32F405的USART3中断读写功能,发送数据正常,但接收时出现异常:
PC向STM32发送数据后,STM32触发中断,RXNE和IDLE标志位被置位,但在调试器中单步执行(仍处于中断处理函数内)时,执行与清除标志无关的操作后,RXNE和IDLE标志竟被自动清除,导致无法针对RXNE标志执行相关操作。
初始化代码
LL_USART_InitTypeDef USART_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; LL_APB1_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART3); LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA); GPIO_InitStruct.Pin = USART1_TX_MB1_Pin|USART1_RX_MB1_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_7; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); USART_InitStruct.BaudRate = 9600; USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B; USART_InitStruct.StopBits = LL_USART_STOPBITS_1; USART_InitStruct.Parity = LL_USART_PARITY_NONE; USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX; USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE; USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16; LL_USART_Init(USART3, &USART_InitStruct); LL_USART_ConfigAsyncMode(USART3); LL_USART_Enable(USART3); NVIC_SetPriority(USART3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); NVIC_EnableIRQ(USART3_IRQn);
中断处理函数
void USART3_IRQHandler(void) { uint8_t x = 0; if (USART3->SR & (USART_SR_NE | USART_SR_FE | USART_SR_PE | USART_SR_ORE)) { LL_USART_ClearFlag_FE(USART3); LL_USART_ClearFlag_NE(USART3); LL_USART_ClearFlag_ORE(USART3); } if (LL_USART_IsActiveFlag_RXNE(USART3)) x = LL_USART_ReceiveData8(USART3); if (LL_USART_IsActiveFlag_TC(USART3)) { LL_USART_TransmitData8(USART3, 0x55); LL_USART_DisableIT_TC(USART3); } }
问题分析与解决方案
1. 基础代码错误修正
- 时钟使能错误:USART3挂载在APB1总线,初始化中
LL_APB1_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART3);参数错误,应改为:LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART3); - GPIO引脚配置错误:当前代码使用了USART1的引脚定义,需根据STM32F405引脚映射,替换为USART3对应的引脚(例如PB10/PB11),并确保复用功能配置正确。
2. 中断使能缺失
当前初始化代码未开启USART3的RXNE和IDLE中断,这会导致标志位触发后无法进入正确的中断处理逻辑,甚至引发异常行为。需添加:
LL_USART_EnableIT_RXNE(USART3); LL_USART_EnableIT_IDLE(USART3); // 若需要IDLE中断则添加
3. 标志自动清除原因与处理
根据STM32F4参考手册:
- RXNE标志仅在读取USART_DR寄存器时自动清除;
- IDLE标志需要先读取USART_SR寄存器,再读取USART_DR寄存器才能清除。
你遇到的单步执行时标志自动清除,可能是调试器自动刷新寄存器视图时,隐含读取了DR寄存器导致的。优化中断处理函数,确保标志清除逻辑符合手册要求:
void USART3_IRQHandler(void) { uint8_t x = 0; volatile uint32_t dummy; // 处理错误标志 if (USART3->SR & (USART_SR_NE | USART_SR_FE | USART_SR_PE | USART_SR_ORE)) { LL_USART_ClearFlag_FE(USART3); LL_USART_ClearFlag_NE(USART3); LL_USART_ClearFlag_ORE(USART3); dummy = USART3->DR; // 读取DR清除错误相关状态 } // 处理RXNE中断 if (LL_USART_IsActiveFlag_RXNE(USART3)) { x = LL_USART_ReceiveData8(USART3); // 添加自定义RXNE处理逻辑 } // 处理IDLE中断 if (LL_USART_IsActiveFlag_IDLE(USART3)) { // 按手册要求清除IDLE标志:先读SR,再读DR dummy = USART3->SR; dummy = USART3->DR; // 添加自定义IDLE处理逻辑 } // 处理发送完成中断 if (LL_USART_IsActiveFlag_TC(USART3)) { LL_USART_TransmitData8(USART3, 0x55); LL_USART_DisableIT_TC(USART3); } }
4. 调试器设置调整
在CubeIDE调试时,关闭寄存器视图的自动刷新功能,手动刷新寄存器,避免调试器读取操作干扰标志位状态。
内容的提问来源于stack exchange,提问作者MatTab
相关产品推荐
相关产品推荐

