STM32F4 - 按钮GPIO输入不起作用

时间:2017-03-10 00:48:59

标签: interrupt gpio stm32f4

我使用的是STM32F469发现板,我试图让外部瞬时按钮工作。

它当前连接到PG11,它被设置为按下它时将引脚连接到MCU提供的+ 5V。在继续之前,我只想说明我在stmf4xx_it.c中使用以下代码来执行去抖动:

#define REFdebounce 200

int In1 = 3;
int In1_0 = 0;
int In1_1 = 0;
int StatoIn1 = 3;

void SysTick_Handler(void)
{
  In1 = HAL_GPIO_ReadPin( GPIOG, GPIO_PIN_11 );

  if ( In1 == 0 )
  {
    In1_0++;
    In1_1 = 0;
    if ( In1_0 >= REFdebounce )
    {
      In1_0 = REFdebounce + 1;
      StatoIn1 = 0;
    }
  }
  else
  {
    In1_0 = 0;
    In1_1++;
    if ( In1_1 >= REFdebounce )
    {
      In1_1 = REFdebounce + 1;
      StatoIn1 = 1;
    }
  }
}

我在头文件inout.h中有以下代码:

typedef void ( * TSelectCallback ) ( int aSelectSignal );

void ConfigSelectPin
(
  TSelectCallback             aSelectCallback
);

然后在inout.c中我有以下代码来设置按钮GPIO引脚:

#define SELECT_SIGNAL_PIN                   GPIO_PIN_11
#define SELECT_SIGNAL_GPIO_PORT             GPIOG
#define SELECT_SIGNAL_GPIO_CLK_ENABLE()     __HAL_RCC_GPIOG_CLK_ENABLE()
#define SELECT_SIGNAL_GPIO_CLK_DISABLE()    __HAL_RCC_GPIOG_CLK_DISABLE()
#define SELECT_SIGNAL_EXTI_IRQn             EXTI15_10_IRQn

void ConfigSelectPin( TSelectCallback aSelectCallback )
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Enable GPIOC clock */
  SELECT_SIGNAL_GPIO_CLK_ENABLE();

  /* Configure washer signal pin as input floating */
  GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStructure.Pull = GPIO_PULLDOWN;
  GPIO_InitStructure.Pin  = SELECT_SIGNAL_PIN;
  HAL_GPIO_Init( SELECT_SIGNAL_GPIO_PORT, &GPIO_InitStructure );

  /* Enable and set EXTI lines 0 Interrupt to the lowest priority */
  HAL_NVIC_SetPriority( SELECT_SIGNAL_EXTI_IRQn, 8, 0 );
  HAL_NVIC_EnableIRQ( SELECT_SIGNAL_EXTI_IRQn );

  SelectCallback = aSelectCallback;
}

void EXTI15_10_IRQHandler( void )
{
  if (__HAL_GPIO_EXTI_GET_IT( SELECT_SIGNAL_PIN ) != RESET) 
  {
    RedLedOn();
    __HAL_GPIO_EXTI_CLEAR_IT( SELECT_SIGNAL_PIN );
    HAL_GPIO_EXTI_IRQHandler( SELECT_SIGNAL_PIN );
  }
}

void HAL_GPIO_EXTI_Callback( uint16_t GPIO_Pin )
{
  if ( GPIO_Pin == SELECT_SIGNAL_PIN )
  {
    YellowLedOn();
    GPIO_PinState pinState;

    //pinState = HAL_GPIO_ReadPin( SELECT_SIGNAL_GPIO_PORT, GPIO_Pin );
    pinState = 1;

    if ( SelectCallback )
      SelectCallback ( pinState );
  }
}

然后在我的main.c文件中,我有以下内容:

/* variable to detect that hardware button is pressed */
static int Select = 0;
extern int StatoIn1;

void SelectIsrCallback( int aSelectSignal )
{
  if ( StatoIn1 == 1 )
  {
    OrangeLedOn();
    Select = 1;
  }
}

然后我使用以下代码来检测按钮是否已被按下并执行我所需的操作

if ( Select )
{ 
  BlueLedOn();
  Select = 0;
}

现在每按一下按钮,EXTI15_10_IRQHandler被红色指示灯打开时确认。

如果我按下按钮很多次,HAL_GPIO_EXTI_Callback最终会被黄色指示灯打开确认。

如果我再按下按钮一次,那么最终会调用SelectIsrCallback并执行我想要的操作,正如橙色和蓝色指示灯打开时所承认的那样。

为什么第一次按下按钮时不会调用HAL_GPIO_EXTI_CallbackSelectIsrCallback?为什么SelectIsrCallback被调用后才会调用HAL_GPIO_EXTI_Callback

注意:我刚刚将YellowLedOn()调用移到了HAL_GPIO_EXTI_Callback中的if语句之前,看看是否是if语句的这个函数在它之前需要加载按钮叫做。它没有任何区别,因此问题在于调用HAL_GPIO_EXTI_Callback函数。

1 个答案:

答案 0 :(得分:1)

好的,所以尽管花了好几天才弄清楚这一点,但事实证明答案很简单。需要切换EXTI15_10_IRQHandler中调用的函数的顺序。即需要首先调用HAL_GPIO_EXTI_IRQHandler,然后需要清除该标志。所以这个:

void EXTI15_10_IRQHandler( void )
{
  if (__HAL_GPIO_EXTI_GET_IT( SELECT_SIGNAL_PIN ) != RESET) 
  {
    RedLedOn();
    **__HAL_GPIO_EXTI_CLEAR_IT( SELECT_SIGNAL_PIN );
    HAL_GPIO_EXTI_IRQHandler( SELECT_SIGNAL_PIN );**
  }
}

需要切换到这个:

void EXTI15_10_IRQHandler( void )
{
  if (__HAL_GPIO_EXTI_GET_IT( SELECT_SIGNAL_PIN ) != RESET) 
  {
    RedLedOn();
    HAL_GPIO_EXTI_IRQHandler( SELECT_SIGNAL_PIN );
    __HAL_GPIO_EXTI_CLEAR_IT( SELECT_SIGNAL_PIN );
  }
}

现在看来很明显,因为在调用中断函数之前你不能清除中断标志,否则它将不会执行。但是,我确信我看到很多例子都是按原来的顺序排列的。