2017-09-27 133 views
1

已有4天了,我正在努力在STM32上设置外部中断,并且我经历了大量阅读和其他人的代码才得到它。但没有运气。 我有两个按钮,当按下其中一个按钮时,我希望点亮一个LED,这个例子只是为了让它工作,我想在继续和构建代码的其余部分之前有一些功能。 如果代码有点杂乱,我很抱歉,但我正在努力提高我的编码技能。 我已经通过手册和数据表,但似乎没有任何帮助。STM32L1上的外部中断设置现在不运行ISR

这里是我的main.c

#include "stm32l1xx_hal.h" 
#include "buttons.h" 

static void MX_GPIO_Init(void); 

bool RightButtonFlag = 0; 
bool LeftButtonFlag = 0; 


int main(void) 
{ 
    HAL_Init(); 
    SystemClock_Config(); 
    controls_Interrupt_Init(); 
    MX_GPIO_Init(); 

    while (1) 
    { 
     if(RightButtonFlag){ 
      Blue_ON(); 
     } 
     if(LeftButtonFlag){ 
      Green_ON(); 
     } 
    } 

} 
static void MX_GPIO_Init(void) 
{ 
    GPIO_InitTypeDef GPIO_InitStruct; 

    /* GPIO Ports Clock Enable */ 
    __HAL_RCC_GPIOC_CLK_ENABLE(); 


    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; 
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; 
    GPIO_InitStruct.Pull = GPIO_PULLUP; 
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 
{ 

其次stm32l1xx_it.c

#include "stm32l1xx_hal.h" 
#include "stm32l1xx.h" 
#include "stm32l1xx_it.h" 
#include "buttons.h" 

extern volatile uint8_t RightButtonFlag; 
extern volatile uint8_t RightButtonFlag; 

void EXTI15_10_IRQHandler(void) 
{ 
    if(GPIOC->IDR & GPIO_IDR_IDR_10){ 
     RightButtonFlag = 1; 
     EXTI->PR |= EXTI_PR_PR10; 
    } 

    if(GPIOC->IDR & GPIO_IDR_IDR_11){ 
      LeftButtonFlag = 1; 
      EXTI->PR |= EXTI_PR_PR11; 
    } 
} 

buttons.c

void controls_Interrupt_Init(void){ 

    RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; /* Enable System Configuration Register */ 


    SYSCFG->EXTICR[3] |= SYSCFG_EXTICR3_EXTI11_PC; /* Set up External Interrupt for Pin 11 Port C */ 
    SYSCFG->EXTICR[3] |= SYSCFG_EXTICR3_EXTI10_PC; /* Set up External Interrupt for Pin 10 Port C */ 

    EXTI->IMR |= EXTI_IMR_MR11; 
    EXTI->IMR |= EXTI_IMR_MR10; 

    EXTI->FTSR |= EXTI_FTSR_TR11; /* Falling trigger Selection Reg. Trigger 11 */ 
    EXTI->FTSR |= EXTI_FTSR_TR10; /* Falling trigger Selection Reg. Trigger 10 */ 

    NVIC_SetPriority(EXTI15_10_IRQn,1); /* Set Interrupt priority for pins 10-15 */ 
    NVIC_EnableIRQ(EXTI15_10_IRQn); /* Enable NVIC for Pins Between 10-15 */ 


} 

和buttons.h

void controls_Interrupt_Init(void); 

#define Blue_ON()   (HAL_GPIO_WritePin(BLUE_LED_PORT, BLUE_LED_PIN, 1)) 
#define Green_ON()   (HAL_GPIO_WritePin(GREEN_LED_PORT, GREEN_LED_PIN, 1)) 
的一部分

我对编码相当陌生,而且我的经验很差,我期望把它搞砸得很简单。

+0

从哪里调用MX_GPIO_Init()?当你在'EXT15_10_IRQHandler()'上设置一个断点时,当你按下按钮时断点会被触发吗? – kkrambo

+0

哦,是的!对不起!它在main()函数中被调用,我通过删除很多与这个问题无关的东西来缩短这段代码,但是我必须在事故中删除MX_GPIO_Init(),但它实际上包含在代码中。我要编辑这个以避免混淆。 –

+0

我在调试器中注意到在内存视图中,相应引脚的PR(挂起寄存器)中的位始终为0,当我尝试将其设置为1时,它仍然为0。 –

回答

3

您必须将标志声明为volatile。这是编译器的一个暗示,即变量可以随时改变,与正常的程序流程无关。

volatile bool RightButtonFlag = 0; 
volatile bool LeftButtonFlag = 0; 

当没有volatile存在,编译器可以假定国旗从未在主循环改变,优化这样的说法,这两个变量将只加载一次,在循环之前。

声明它们volatile只在中断处理程序的范围内没有好处,因为优化仍将发生在main(),其中volatile声明不可见。

将声明移动到头文件是一个很好的做法,并且在引用该变量的所有位置都包含该头。然后编译器可以检查这些类型是否确实兼容。

UPDATE

中断处理程序没有什么意义。您设置EXTI检测到下降边缘,然后检查输入是否为。由于机械按钮的弹跳效应,检查GPIO数据寄存器是不可靠的。

您应该在处理程序中检查EXTI->PR,并使用简单赋值而不是|=来重置待处理位,否则可能会意外清除另一个待处理位。

void EXTI15_10_IRQHandler(void) 
{ 
    if(EXTI->PR & EXTI_PR_PR10){ 
     RightButtonFlag = 1; 
     EXTI->PR = EXTI_PR_PR10; 
    } 

    if(EXTI->PR & EXTI_PR_11){ 
     LeftButtonFlag = 1; 
     EXTI->PR = EXTI_PR_PR11; 
    } 
} 

您仍然可以检查的地方,如果GPIOC->IDR实际上反映了按钮的状态,以消除可能的硬件问题。

您也可以尝试从调试器或代码中设置EXTI->SWIER来模拟按钮按下。

+0

感谢您的回应。我添加了易失性前缀,它并没有帮助,无论出于何种原因,我试图用于EXTI的两个引脚的PR(挂起寄存器)位不会重置为1,我想它应该设置为1以等待外部中断事件。我会深入研究调试器,看看我是否找到其他的东西。 –

+0

您对阅读'GPIO-> IDR'绝对正确!最重要的是,我将'PUPDR'设置为双引脚上拉,并期望它读取'1',但当按下按钮以使其工作时,我需要从'GPIO-> IDR'读'0'。我尝试在'EXTI-> SWIER'中设置位,并且ButtonFlag成功切换到1,但使用外部中断运行它仍然没有运气。我会深入一点,看看还有什么不对... –

+0

我发现它!它是'SYSCFG-> EXTICR [x]',其中'EXTICR3'的'x'应该是2。我一直在通过调试器进行挖掘,并且发现我在“EXTICR4”中设置了位,而不是在“EXTICR3”中。就像我提到的那样,这是一个简单的菜鸟错误。谢谢你的帮助!我实际上通过试图解决这个问题学到了很多东西。 –