Embedded 带PA0按钮的STM32F303VCT6外部中断赢得';t形开关发光二极管

Embedded 带PA0按钮的STM32F303VCT6外部中断赢得';t形开关发光二极管,embedded,stm32,interrupt-handling,Embedded,Stm32,Interrupt Handling,我想使用一个连接到PA0的按钮作为外部中断,在按下按钮时切换PE14上的LED。但是,调用configure\u PA0函数似乎不起作用 我在while循环中做了一个简单的闪烁指令来测试,结果是当我调用configure\u PA0时,LED一直亮着 如果不调用它,LED将正常闪烁,因此我认为这一定是该功能出了问题 #包括“stm32f30x.h” 无效延迟(挥发性uint32_t计数){ 而(计数>0) 计数--; } 无效初始发光二极管(){//PE14上的初始发光二极管 RCC_AHBPe

我想使用一个连接到PA0的按钮作为外部中断,在按下按钮时切换PE14上的LED。但是,调用
configure\u PA0
函数似乎不起作用

我在while循环中做了一个简单的闪烁指令来测试,结果是当我调用
configure\u PA0
时,LED一直亮着

如果不调用它,LED将正常闪烁,因此我认为这一定是该功能出了问题

#包括“stm32f30x.h”
无效延迟(挥发性uint32_t计数){
而(计数>0)
计数--;
}
无效初始发光二极管(){//PE14上的初始发光二极管
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE,启用);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14;
GPIO_InitStructure.GPIO_OType=GPIO_OType\u PP;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
GPIO_Init(GPIOE和GPIO_InitStructure);
}
无效配置页面0(无效){
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,启用);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,启用);
//PA0作为按钮初始化
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;
GPIO_InitStruct.GPIO_OType=GPIO_OType\u PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd\u UP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA和GPIO_InitStruct);
//EXTI init
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
EXTI_InitStruct.EXTI_Line=EXTI_Line 0;
EXTI_InitStruct.EXTI_LineCmd=ENABLE;
EXTI_InitStruct.EXTI_Mode=EXTI_Mode\u中断;
EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger\u上升;
EXTI_Init(&EXTI_InitStruct);
//NVIC初始化
NVIC_InitStruct.NVIC_IRQChannel=EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0x00;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=0x00;
NVIC_InitStruct.NVIC_IRQChannelCmd=启用;
NVIC_Init(&NVIC_InitStruct);
}
无效切换_PE14(){
如果(GPIO_读输出数据位(GPIOE,GPIO_引脚_14)==0)
GPIO_挫折(GPIOE,GPIO_引脚_14);
其他的
GPIO_复位位(GPIOE、GPIO_引脚_14);
}
//处理pa0中断
void EXTI0_IRQHandler(void){
if(EXTI_GetITStatus(EXTI_Line0)!=RESET){
切换_PE14();
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
内部主(空){
init_LED();
配置_PA0();
而(1){
延迟(400);
}
返回0;
}
更新 我通过将处理程序定义放入
extern“C”{..}
括号中修复了它。显然,如果您使用
C++
编写代码,就必须这样做

更新

首先,感谢您让其他读者知道! 让我解释一下这些发现的因果关系:

。。。我将处理程序定义放入
extern“C”{/*..*/}
括号。 显然,如果你在C++中编码,你必须这样做。

在C++编程时(即,对于C和C++中都有效的语言特征,当使用C++编译器构建程序时),链接器所使用的目标代码中<强> C++符号和<强> C符号有区别。 简而言之,这是因为C++标识符必须通过某种类型的信息来扩展,以支持多态性。 详细说明

<>任何未定义代码>外部的C/<代码>限定符的C++函数将得到扩展的(“被损坏的”)符号。 这也适用于像现在的情况一样,输入到C++编译器中的“模糊”函数。 任何
extern C
函数(以及由C编译器翻译的任何函数,如果混合编译器的话)都将变成一个名称不混的链接器符号(通常仅由一些下划线扩展,具体取决于使用的工具链)

要点是:汇编函数的行为大部分类似于C函数——汇编代码中引用/定义的函数符号将按原样传递给链接器。 通常(在本例中),STM32中断向量表的定义也是如此 (以下两个代码段均取自
startup_stm32l476xx.s
):

对于链接到默认STM32CubeF3/STM32CubeMX代码中的
DefaultHandler
weak
函数定义

/*******************************************************************************
 *
 * Provide weak aliases for each Exception handler to the Default_Handler.
 * As they are weak aliases, any function with the same name will override
 * this definition.
 *
 *******************************************************************************/

.weak   NMI_Handler
.thumb_set NMI_Handler,Default_Handler

/*...*/

.weak   EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler

.weak   EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler

/*...*/
这意味着链接器找到了

  • 向量表中对C符号
    EXTI0\u IRQHandler
    的引用
  • C符号的(弱但唯一)定义
    EXTI0\u IRQHandler
  • 基于<>代码> EXTI0IIrqHANDLUT < /LI>的一个被破坏的C++符号定义(非弱但不匹配)定义
    由于未被引用,它将(1.)与(2.)匹配,并将(3.)丢弃,因此在外部引脚上产生的第一个中断将MCU扔进了无限循环
    DefaultHandler
    ,LED停止闪烁。

    在跳入中断之前,您是否先轮询gpio成功?在那之后,在将中断启用到核心之前,您是否轮询了中断状态?我对此有点陌生,所以我不确定是否正确理解您的意思。如果你问我是否可以获取按钮状态并用它切换led。。是的,我可以读取输入数据位并操作led。但是,如果我添加了EXTI/NVIC部分,我就不能再这样做了(NVIC启用部分是破坏它的原因,这是我测试的)。第二个问题:您的意思是我应该将EXTI设置为禁用并使用getITStatus函数读取状态吗?请在调试器中逐步检查您的代码。它的行为和你期望的一样吗?
    是否配置\u PA0
    返回?在
    EXTI0\u IRQHandler
    toggle\u PE14
    上设置断点。这些函数是否执行过?这些函数中的条件是否像您期望的那样工作?我试着调试它并注意到了这一点
    /*******************************************************************************
     *
     * Provide weak aliases for each Exception handler to the Default_Handler.
     * As they are weak aliases, any function with the same name will override
     * this definition.
     *
     *******************************************************************************/
    
    .weak   NMI_Handler
    .thumb_set NMI_Handler,Default_Handler
    
    /*...*/
    
    .weak   EXTI0_IRQHandler
    .thumb_set EXTI0_IRQHandler,Default_Handler
    
    .weak   EXTI1_IRQHandler
    .thumb_set EXTI1_IRQHandler,Default_Handler
    
    /*...*/