Skip to main content
欢迎来到PAWPAW技术文档网站了解更多信息

处理按钮按下事件

为了处理按钮按下事件,需要一个任务在引脚数值发生变化时触发事件。可以利用select结构和pinsneq谓词在select case中实现这一点:

// 此函数是可组合的 - 它可以与其他任务一起在逻辑核上运行。
[[combinable]]
void task1(port p_button)
{
// 记录端口的最后读取值。
int current_val = 0;
while (1) {
select {
// 当按钮的值发生变化时触发事件
case p_button when pinsneq(current_val):> int new_val:
if (new_val == 1) {
printf("按钮弹起\n");
} else {
printf("按钮按下\n");
}
current_val = new_val;
break;
}
}
}

这段代码将在I/O引脚值发生变化时做出反应。然而,由于按钮会反复弹起和按下,一旦按钮被按下,I/O引脚的值会迅速多次变化。为了避免对每一次变化做出反应,可以添加一个去抖动期。

为了实现这一点,在select case中添加一个保护条件。该保护条件表示,除非变量is_stable的值为真(即非零),否则不对按钮做出反应。当按钮被按下时,is_stable被设置为0,并设置了一个超时。另外一个case处理了超时到期(使用一个计时器),此时is_stable被重新设置为1。

[[combinable]]
void task1a(port p_button)
{
int current_val = 0;
int is_stable = 1;
timer tmr;
const unsigned debounce_delay_ms = 50;
unsigned debounce_timeout;
while (1) {
select {
// 如果按钮是“稳定的”,则在I/O引脚值发生变化时做出反应
case is_stable => p_button when pinsneq(current_val):> current_val:
if (current_val == 1) {
printf("按钮弹起\n");
} else {
printf("按钮按下\n");
}
is_stable = 0;
int current_time;
tmr :> current_time;
// 计算去抖动周期后的事件时间
// 注意,XS1_TIMER_HZ在timer.h中定义
debounce_timeout = current_time + (debounce_delay_ms * XS1_TIMER_HZ);
break;
// 如果按钮不稳定(即来回弹动),则在计时器达到超时时重新进入稳定期
case !is_stable => tmr when timerafter(debounce_timeout):> void:
is_stable = 1;
break;
}
}
}