You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者徐亦昶

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:35:21