-1

我是微控制器的初学者。我正在使用定制的 STM8 板并使用板载按钮来计算按下的次数。我无法让它工作,这是我的代码,如果可以,请提供帮助 - 开关连接到 PA1。代码的相关部分 -

void setup()
{
  GPIO_DeInit(GPIOA);
  GPIO_DeInit(GPIOB);
  GPIO_DeInit(GPIOC);
  GPIO_DeInit(GPIOD);

  GPIO_Init(GPIOA, GPIO_PIN_1, GPIO_MODE_IN_PU_IT); // **PA1 SWITCH**
}

void scan()
{

  if (GPIO_ReadInputPin(GPIOA, GPIO_PIN_1) == 0)
  {
    do 
    {
    }
    while(GPIO_ReadInputPin(GPIOA, GPIO_PIN_1) == 0);
    
    key_count++;
  }    
}    
4

1 回答 1

0

这里有很多猜测,但是由于您似乎在轮询按钮而不是使用中断,因此您的初始化不正确:

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()

于 2021-07-06T13:27:37.850 回答