STM32L1上的外部中断设置不会运行ISR

时间:2017-09-27 02:17:39

标签: c embedded external interrupt stm32

现在已经4天了,我正努力在我的STM32上设置外部中断,并且我已经通过了大量的阅读和其他人的代码来获取它。但没有运气。 我有两个按钮,当按下其中任何一个按钮时,我希望点亮一个LED,这个例子只是为了使它工作,我希望在继续操作并构建其余代码之前有一些功能。 如果代码有点乱,我很抱歉,但我正在努力解决我的编码技巧问题。 我已经阅读了手册和数据表,但似乎没有任何帮助。

这是我的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))

我对编码很新,而且由于我的经验不佳,我希望能搞得很简单。

1 个答案:

答案 0 :(得分:3)

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

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

当那里没有volatile时,编译器可以假设标志在主循环中永远不会改变,并以这种方式优化它,变量将在循环之前加载一次。

仅在中断处理程序的范围内声明它们volatile没有用,因为优化仍将在main()中进行,volatile声明不可见。

最好将声明移到头文件中,并在引用变量的任何地方包含该头。然后编译器可以检查类型是否确实兼容。

<强>更新

中断处理程序没什么意义。设置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来模拟按下按钮。