-1

我正在构建一个键盘,一些固件在用 C 语言编程的无线模块上运行。我正在尝试推出我自己的去抖动算法,并且可以使用一些帮助。本质上,这是代码的布局方式:

#define DEBOUNCE 5- 这个值可以是从 1(不建议,不是真正的去抖动)到无穷大(出于显而易见的原因也不建议)的任何值。我用这个去抖动 32 个按钮,所以接下来我使用以下方法创建一个 32 位整数数组:

static uint32_t key_integration[DEBOUNCE];

在每次扫描输入(1KHz 轮询率)时,我将数组的倒数第二个项目移动到最后一个,将倒数第三个移动到倒数第二个,等等,直到我最终输入键的原始扫描到第 0 个数组项。(附带的问题:比仅仅从 0 迭代循环到 DEBOUNCE-2 更简单的方法?如果我有一个 (32*DEBOUNCE) 位整数,我会使用按位移位,但是......无论如何。)

现在我遇到困难的棘手部分:将数组结果与当前(去抖动)键状态进行比较。本质上,如果 key_integration int 的位 X 是 1 是所有数组,我想将它与当前(去抖动)键状态进行异或,以查看它是否已更改。如果 key_integration int 的每个位 X 在所有数组中都是 0,我也想做同样的事情。如果位 X 在数组中分散为 1 和 0,则它仍在去抖动并且不需要进行比较。

我目前对如何将 key_integration 数组与去抖键状态 int 进行比较感到困惑。我非常感谢有关如何 A)比较它们或 B)重构代码以更简单的方式完成相同结果的建议。我绝对不能相信我所想的就是最好的方法。

4

1 回答 1

0

您可以相当容易地计算出哪些键始终为零或始终为一的掩码(伪代码)

alwaysZ = -1
alwaysO = -1
for (int i = 0; i < DEBOUNCE; i++)
    alwaysZ &= ~keys[i]
    alwaysO &= keys[i]

这样就很容易确定哪些键保持不变(但处于任一极性):stable = alwaysZ | alwaysO

虽然这需要在每个轮询时刻重新计算,但这是可以避免的。显然,stable[i]如果设置第 i 个位的次数为 0 或DEBOUNCE(也许DEBOUNCE - 1,取决于您定义该常数的含义,但关键是它将是 0 或“所有内容”),则该位将被设置。所以这里有一个替代方案:保留一个counts数组,计算每个按钮在整个去抖动窗口中发现它处于关闭状态的次数。为每个当前按下的按钮添加一个,从每个按下的按钮减去一个DEBOUNCE到过去的步骤。

通过计数数组,您可以判断每个按钮在恒定时间内是否稳定,与去抖动量无关。不利的一面是,您必须明确检查每个计数,而使用位掩码您可以立即确定任何按钮是否稳定,然后提前退出。

至于附带的问题,您可以使用标准的循环缓冲区技术来避免移动数据本身,只需通过调整索引来虚拟移动它。但这也不是免费的,因为 DEBOUNCE=5 我不会那样做。由于开销是恒定的,因此它可以很好地扩展到巨大的去抖动值。您通常可以避免进行实际的模运算,因为您只是在递增一个索引(因此,如果您到达末尾,您可以递增并返回 0),而不是随机索引到缓冲区的中间。

于 2017-07-29T00:35:01.923 回答