STM32F103C8T6中USART3_IRQHandler无法进入的问题排查
STM32F103C8T6 USART3中断无法触发问题排查
问题描述
使用STM32F103C8T6芯片,PA2、PA3引脚连接一个超声波模块,PB10、PB11引脚连接另一个超声波模块。代码中EN_USART2和EN_USART3均设置为1,USART2的中断服务函数可正常执行,但USART3的USART3_IRQHandler无法进入。在USART3中断函数内的a = USART_ReceiveData(USART3);语句后添加printf("p")调试,串口调试窗口无输出,但main函数中USART1的printf输出正常,说明USART1工作正常。USART3代码写法与USART2类似,对比模板代码未发现明显错误,求排查原因。
相关代码
usart.c 部分代码
#if EN_USART2 u16 _distance1=0; u16 distance1=0; void USART2_Init(u32 bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_InitStructure.USART_BaudRate = bound; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStructure); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); USART_Cmd(USART2, ENABLE); } void USART2_IRQHandler(void){ u8 a; if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET){ a =USART_ReceiveData(USART2); if(a!=0xa5) _distance1=(_distance1<<8)|a; else { distance1=_distance1; _distance1=0; } } } #endif #if EN_USART3 u16 _distance2=0; u16 distance2=0; void USART3_Init(u32 bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB, &GPIO_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_InitStructure.USART_BaudRate = bound; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART3, &USART_InitStructure); USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); USART_Cmd(USART3, ENABLE); } void USART3_IRQHandler(void){ u8 a; if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET){ a =USART_ReceiveData(USART3); if(a!=0xa5) _distance2=(_distance2<<8)|a; else { distance2=_distance2; _distance2=0; } } } #endif
main.c 代码
#include "stm32f10x.h" #include "delay.h" #include "system.h" #include "usart.h" // Device header int main(void) { SystemInit(); USART1_Init(115200); USART2_Init(115200); USART3_Init(115200); while(1) { printf("difference: %dmm\n",distance1-distance2); delay_ms(100); } }
排查与解决思路
- 检查NVIC优先级分组:STM32F1系列的NVIC优先级分组必须全局统一,比如通过
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);设置分组2(2位抢占优先级+2位子优先级)。如果USART3的抢占/子优先级配置超出当前分组的范围,会导致中断无法触发。确保所有中断的优先级配置都符合当前分组规则。 - 清除USART3中断残留标志:如果USART3存在未处理的溢出错误(ORE)或其他中断标志,会阻塞RXNE中断触发。在USART3初始化完成后,添加代码清除所有相关中断标志:
USART_ClearITPendingBit(USART3, USART_IT_RXNE | USART_IT_ORE | USART_IT_FE); - 验证硬件接线与模块输出:用示波器或逻辑分析仪检测PB11(USART3_RX)引脚是否有超声波模块发送的串口波形,确认模块是否正常输出数据,同时检查PB10/PB11的RX/TX是否接反,接线是否松动。
- 确认全局中断使能:确保代码中开启了全局中断,可在main函数开头添加
__enable_irq();(标准库函数),虽然SystemInit()通常会开启,但不排除被其他代码意外关闭。 - 检查变量作用域:确认
distance2和_distance2在usart.h中被声明为extern,否则main函数中直接使用会产生未定义行为(虽然这不会直接导致中断不触发,但可能影响后续逻辑)。 - 排查USART3时钟与初始化:确认
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);执行正常,USART3属于APB1总线,时钟使能不能错。同时检查是否有其他代码在初始化后修改了USART3的配置。
内容的提问来源于stack exchange,提问作者徐亦昶
相关产品推荐
相关产品推荐

