基本硬件编程问题

问题描述 投票:0回答:1

我在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上运行(此处扩展模块的类型无关紧要)。事实是,此方法仅会停止动画一会,并且无法按我希望的那样工作。您可以更正此程序以使其正常运行吗?

c++ hardware
1个回答
1
投票

您可以更正此程序的任何内容以使其正常工作吗?正确吗?

我的猜测是,您正在尝试向设计中添加“人机交互”方面。您当前的方法依赖于一个(按钮位置)样本,该样本由a)您的应用程序和b)人的手指随机计时。这个时间根本不可靠,但是校正可能不太困难。


注1:“简单”机械按钮在激活或释放过程中将“弹起”(是的,两种方式都可以)。这意味着在按钮按下或释放附近的数(tbd)毫秒(?)内,软件“看到”的值(几微秒)是不可预测的。

注2:解决此问题的另一种方法是,您的状态值存在两个位置:在物理按钮中和变量“ GPIO_PinState state;”中。恕我直言,状态值只能位于一个位置。两个位置总是一个错误。

解决方案,然后(如果您认为)是决定保留一个状态“记录”,而消除另一个状态。恕我直言,我认为您想保留该按钮,这似乎是您的人工输入。要明确的是,您要消除变量“ GPIO_PinState状态;”


此行:

state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_15);

一次采样开关状态。

但是,您已经知道该设计不能依靠正确的阅读。毕竟,您的用户可能只是按下或释放了按钮,并且在采样时它只是在弹跳。

在开始累积样本之前,您应该注意,反弹可能会持续多于几微秒。我已经看到一些开关会反弹到10毫秒或更长时间。如果可以使用测试设备,我将其连接起来并查看您按钮的特性。如果不能,那么您可以尝试调整以下样本累加器的控件。


因此,我们如何“积累”足够的样本以使自己确信我们可以知道开关的状态?

考虑多个采样,在时间上间隔很短的延迟(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
}

FYI-上面的方案进行了3种调整,以处理不同的开关弹跳持续时间...您需要做一些实验。我将从20的最大样本开始。我不建议sleep_for ...您未提供有关系统的其他信息。

祝你好运。>>

已经很长时间了,但是我想我记得电信基础设施设备上的按钮在5到15毫秒之间跳动。

© www.soinside.com 2019 - 2024. All rights reserved.