This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS570LC4357:按钮去抖

Guru**** 2828555 points

Other Parts Discussed in Thread: HALCOGEN

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1604820/tms570lc4357-push-button-debounce

器件型号: TMS570LC4357
主题中讨论的其他器件: HALCOGEN

您好、

我想使用 HDK 电路板上的内部按钮。 但按钮不能稳定工作。 有时、寄存器的值会发生变化、有时会在按下按钮时更改值。 该状态是不可预测的。 如何编写去抖函数? 或者是否有示例项目?


 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Dobby:

    您遇到的不稳定是一个称为“按钮反弹“的常见问题。 按下或松开机械按钮时,触点不会完全闭合或完全断开 — 它们会在 5-20ms 内多次反弹、从而导致 GPIO 寄存器意外变化。

    遗憾的是、我没有任何现成的示例、因为大多数这类要求都将由客户自己处理、所以我以前从未遇到过这类问题。

    我们有内部 AI、它建议使用如下所示的几个代码流、您可以采用其中的任何一种方法。

    方法 1:

    // Debounce configuration
    #define DEBOUNCE_TIME_MS    20    // Typical debounce time: 10-20ms
    #define BUTTON_PRESSED      0     // Assuming active low with pull-up
    #define BUTTON_RELEASED     1
    
    // Global variables
    static uint32_t lastButtonState = BUTTON_RELEASED;
    static uint32_t buttonStateCounter = 0;
    static uint32_t stableButtonState = BUTTON_RELEASED;
    
    // Call this function periodically (e.g., every 1ms from a timer interrupt)
    uint32_t debounceButton(uint32_t currentButtonState)
    {
        if (currentButtonState != lastButtonState) {
            // Button state changed, reset counter
            buttonStateCounter = 0;
            lastButtonState = currentButtonState;
        } else {
            // Button state is stable, increment counter
            if (buttonStateCounter < DEBOUNCE_TIME_MS) {
                buttonStateCounter++;
            }
            
            // If stable for debounce time, update stable state
            if (buttonStateCounter >= DEBOUNCE_TIME_MS) {
                stableButtonState = currentButtonState;
            }
        }
        
        return stableButtonState;
    }
    
    // Usage in your main loop or timer ISR
    void checkButton(void)
    {
        uint32_t rawButtonState = gioGetBit(gioPORTA, BUTTON_PIN); // Read GPIO
        uint32_t debouncedState = debounceButton(rawButtonState);
        
        if (debouncedState == BUTTON_PRESSED) {
            // Button is pressed (stable)
            // Your action here
        }
    }

    方法 2:

    typedef enum {
        BUTTON_STATE_RELEASED,
        BUTTON_STATE_PRESSED,
        BUTTON_STATE_DEBOUNCING_PRESS,
        BUTTON_STATE_DEBOUNCING_RELEASE
    } ButtonState_t;
    
    ButtonState_t buttonStateMachine(uint32_t rawInput)
    {
        static ButtonState_t state = BUTTON_STATE_RELEASED;
        static uint32_t debounceCounter = 0;
        
        switch(state) {
            case BUTTON_STATE_RELEASED:
                if (rawInput == BUTTON_PRESSED) {
                    state = BUTTON_STATE_DEBOUNCING_PRESS;
                    debounceCounter = 0;
                }
                break;
                
            case BUTTON_STATE_DEBOUNCING_PRESS:
                if (rawInput == BUTTON_PRESSED) {
                    debounceCounter++;
                    if (debounceCounter >= DEBOUNCE_TIME_MS) {
                        state = BUTTON_STATE_PRESSED;
                        // Trigger button press event here
                    }
                } else {
                    state = BUTTON_STATE_RELEASED;
                }
                break;
                
            case BUTTON_STATE_PRESSED:
                if (rawInput == BUTTON_RELEASED) {
                    state = BUTTON_STATE_DEBOUNCING_RELEASE;
                    debounceCounter = 0;
                }
                break;
                
            case BUTTON_STATE_DEBOUNCING_RELEASE:
                if (rawInput == BUTTON_RELEASED) {
                    debounceCounter++;
                    if (debounceCounter >= DEBOUNCE_TIME_MS) {
                        state = BUTTON_STATE_RELEASED;
                        // Trigger button release event here
                    }
                } else {
                    state = BUTTON_STATE_PRESSED;
                }
                break;
        }
        
        return state;
    }

    硬件配置提示

    1. 启用内部上拉/下拉 :使用适合您的按钮电路的内部上拉或下拉电阻器配置 GPIO

    2. HALCoGen 配置 :使用 HALCoGen 正确配置 GPIO :

      • 将引脚设置为输入
      • 如果按钮在按下时接地、则启用上拉
      • 如果按下该按钮时连接到 VCC、则启用下拉

    用于定期采样的计时器设置

    您将需要一个计时器来定期调用去抖功能(建议每 1ms 一次):

    // In HALCoGen, configure RTI (Real-Time Interrupt) for 1ms period
    void rtiNotification(uint32 notification)
    {
        if(notification == rtiNOTIFICATION_COMPARE0) {
            // Call your button check function here
            checkButton();
        }
    }

    --

    此致、
    Jagadish。