这里有很多猜测,但是由于您似乎在轮询按钮而不是使用中断,因此您的初始化不正确:
GPIO_Init( GPIOA, GPIO_PIN_1, GPIO_MODE_IN_PU_NO_IT ) ;
// ^^^
感谢@Sorenp 在评论中发现了这一点
即使使用正确的输入模式,该scan()
功能也会阻塞(您的程序将在按住按钮时停止执行任何有用的操作),并且不提供开关去抖动(开关很少干净地改变状态)。因此,我建议使用去抖动时间进行非阻塞轮询:
#define DEBOUNCE_MILLIS 20
void scan()
{
// Button states
typedef enum
{
BTN_DN = 0,
BTN_UP = 1
} tBtnState ;
static tBtnState previous_button_state = (tBtnState)GPIO_ReadInputPin(GPIOA, GPIO_PIN_1) ;
static unsigned long timestamp = 0 ;
tBtnState current_button_state = (tBtnState)GPIO_ReadInputPin(GPIOA, GPIO_PIN_1) ;
// If button down...
if( current_button_state == BTN_DN )
{
// ... and was previously up (transition event)...
if( previous_button_state == BTN_UP )
{
timestamp = millis() ;
previous_button_state = BTN_DN ;
key_count++ ;
}
}
// If button has been released for at least the debounce period...
else if( millis() - timestamp > DEBOUNCE_MILLIS )
{
previous_button_state = BTN_UP ;
}
}
然后,您可以scan()
在执行代码需要执行的任何其他操作时简单地“频繁”调用:
void main()
{
// Initialise
setup() ;
// executive loop
for(;;)
{
// Count button presses
scan() ;
// Do other stuff
}
}
scan()
处理自己的时间,因此不需要以特定的速率调用 - 只要足够快以捕捉任何按钮按下,因此您在循环中执行的任何其他操作都必须同样非阻塞,以便循环迭代并且永远不会超过说 100 毫秒到达scan()
.
由于您将其标记为 [arduino],我假设 Arduinomillis()
功能可用,但尚不清楚这是否真的是 Arduino 代码。酌情替换您自己的计时函数或标准库clock()
。