我使用的是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_Callback
和SelectIsrCallback
?为什么SelectIsrCallback
被调用后才会调用HAL_GPIO_EXTI_Callback
?
注意:我刚刚将YellowLedOn()
调用移到了HAL_GPIO_EXTI_Callback
中的if语句之前,看看是否是if语句的这个函数在它之前需要加载按钮叫做。它没有任何区别,因此问题在于调用HAL_GPIO_EXTI_Callback
函数。
答案 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 );
}
}
现在看来很明显,因为在调用中断函数之前你不能清除中断标志,否则它将不会执行。但是,我确信我看到很多例子都是按原来的顺序排列的。