0

我正在使用 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都会被红色 LED 亮起确认。

如果我一直按下按钮,很多很多次,HAL_GPIO_EXTI_Callback最终将被黄色 LED 亮起称为确认。

如果我继续按下按钮更多次,那么最终SelectIsrCallback会调用并执行我想要的操作,正如橙色和蓝色 LED 亮起所确认的那样。

为什么在第一次按下按钮时不会调用HAL_GPIO_EXTI_Callbackand ?SelectIsrCallback为什么SelectIsrCallback一旦HAL_GPIO_EXTI_Callback被调用就不会被调用?

注意:我刚刚将YellowLedOn()调用移到 if 语句之前,HAL_GPIO_EXTI_Callback以查看是否是 if 语句的这个函数在调用之前需要大量按钮按下。它没有任何区别,所以问题在于HAL_GPIO_EXTI_Callback函数的调用。

4

1 回答 1

1

好的,尽管花了几天时间来解决这个问题,但事实证明答案很简单。调用函数的顺序EXTI15_10_IRQHandler需要切换。即HAL_GPIO_EXTI_IRQHandler需要先调用 b 然后清除标志。所以这:

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 );
  }
}

现在这似乎很明显,因为您不能在调用中断函数之前清除中断标志,否则它将不会执行。但是,我确信我看到了很多例子,它们是按照我最初拥有这些功能的顺序排列的。

于 2017-03-10T01:52:43.700 回答