在B站刷到的一位Up主分享的一种消抖写法。
【C语言位运算经典应用:单片机按键软件消抖算法[01] 背景及预告】 https://www.bilibili.com/video/BV1Sb421n7Zv/
来源于《embedded system dict》 Page71
这段代码是一个用于消除八个输入引脚抖动的函数。每次重新读取原始状态时,只需调用此函数,并使用返回的值作为去抖后的信号。如果需要三个或更多连续相同的读数,只需将`previous`替换为两个或更多的先前状态。如果需要是八个以上的引脚,改变传参的数据类型即可。
uint8_t debounce(uint8_t current) {
static uint8_t asserted = 0x00; // 初始化断言状态为全0
static uint8_t previous = 0x00; // 初始化前一个状态为全0
// 比较每个输入的当前和先前状态
asserted |= (previous & current); // 断言新“开”的输入
asserted &= (previous | current); // 清除新“关”的输入
// 更新历史记录
previous = current;
// 返回去抖后的输入给调用者
return (asserted);
}
这个函数的工作方式如下:
1. 它使用两个静态变量 asserted和 previous来跟踪引脚的前一个状态。这些变量被初始化为 0x00(所有位都关闭)。
2. 然后,函数通过位操作比较每个引脚的当前状态和先前状态。
asserted |= (previous & current);这行代码断言(打开)任何先前关闭而现在已经打开的引脚。它通过对 previous和 current 执行位与操作来获取从关闭变为打开的引脚的掩码。然后与 asserted进行位或操作,从而在 asserted中打开这些特定的位。
asserted &= (previous | current); 这行代码清除(关闭)任何先前打开而现在已经关闭的引脚。它通过对 previous和 current 执行位或操作来获取从打开变为关闭的引脚的掩码。然后与 asserted进行位与操作,从而在 asserted 中关闭这些特定的位。
3. 处理完所有引脚后,函数更新 previous 变量,以便下次调用时保存当前状态。
4. 最后,函数返回 asserted变量,现在它包含了引脚的去抖状态。
评论区有另外的一种写法:
一个变量存按键变化状态,一个存按键变化类型。
连续两次调用KeyRead()函数可以判断按键的长短按事件。第一次调用时,Trg和Cont变量都会被更新为当前按键状态。第二次调用时,Trg变量会再次被更新,但Cont变量保持不变。通过比较第二次调用时的Trg和Cont值,我们可以确定按键是否发生了状态变化以及是短按还是长按事件。