基本硬件编程问题

Problem with programming a basic hardware

我在 LED 上显示动画。按下按钮时,动画必须停止,然后在再次按下按钮后继续。 有一种处理按钮的方法:

void checkButton(){

GPIO_PinState state;

state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15);
if (state == GPIO_PIN_RESET) {
    while(1){
        state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15);
        if (state == GPIO_PIN_SET){
            break;
        }
    }
    //while (state == GPIO_PIN_RESET) {
        //state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15);
    //}
}
}

GPIO_PIN_SET 是默认的按钮位置。 GPIO_PIN_RESET是按下按钮时的条件。评论部分是我尝试的而不是 while(1){...} 循环。 checkButton()方法在主循环中时不时被调用为运行。 STM32上的程序运行s带有扩展模块(这里扩展模块的类型无关紧要)。 事实上,这种方法只是暂时停止了动画,并没有像我希望的那样工作。您能否更正此程序的任何内容以使其正常运行?

Could you correct anything about this program to make it work properly?

我的猜测是您正试图在设计中添加 'human interaction' 方面。您当前的方法依赖于由 a) 您的应用程序和 b) 人的手指随机定时的单个(按钮位置)样本。这个时间点简直不靠谱,不过改正应该不会太难。


注意 1:'simple' 机械按钮在激活或释放期间会 'bounce'(是的,无论哪种方式)。这意味着软件 'sees'(几微秒内)的值在按下或释放按钮附近的几 (tbd) 毫秒 (?) 内是不可预测的。

注意 2:看待这个问题的另一种方式是,您的状态值存在于两个地方:在物理按钮中和在变量 "GPIO_PinState state;" 中。恕我直言,状态值只能驻留在一个位置。两个位置总是错误的。

然后(如果您相信)解决方案是决定保持一种状态 'record',并消除另一种状态。恕我直言,我想你想保留按钮,这似乎是你的人工输入。明确地说,您想消除变量 "GPIO_PinState state;"


这一行:

state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15);

对开关状态采样一次。

但是,您已经知道这种设计不能依赖于一次读取是否正确。毕竟,您的用户可能刚刚按下或释放按钮,它只是在采样时弹跳。

在我们开始累积样本之前,您应该知道弹跳可能持续的时间远远超过几微秒。我见过一些开关弹跳长达 10 毫秒或更长时间。如果有测试设备,我会把它连接起来,看看你的按钮的特性。如果不行,那好,你可以尝试调整下面示例累加器的控件。


那么,我们如何 'accumulate' 获得足够的样本来确信我们可以知道开关的状态?

考虑多个样本,时间间隔很短(2 个对照?)。我认为你可以简单地积累它们。第一个达到 tbr - 5(或 10 或 100?)样本的计数获胜。因此,旋转采样、延迟并递增两个计数器之一:

stateCount [2] = {0,0};  // state is either set or reset, init both to 0
//              vvv-------max samples
for (int i=0; i<100; ++i)  // worst case how long does your  switch bounce
{
    int sample = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15);  // capture 1 sample

    stateCount[sample] += 1;  // increment based on sample

    // if 'enough' samples are the same, kick out early
    //                       v ---- how long does your switch bounce
    if (stateCount[sample] > 5) break; // 5 or 10 or 100 ms

    // to-be-determined --------vvv --- how long does switch bounce
    std::this_thread::sleep_for(1ms);  // 1, 3, 5 or 11 ms between samples
    // C++ provides, but use what is available for your system
    // and balanced with the needs of your app
}

仅供参考 - 上面的方案有 3 个调整来处理不同的开关弹跳持续时间......您需要做一些实验。我会从 20 个最大样本开始。我没有 sleep_for 的建议......你没有提供关于你的系统的其他信息。

祝你好运。

已经很久了,但我想我记得电信基础设施设备上的按钮弹跳了 5 到 15 毫秒。