按键检测的消抖和实现
在送药小车中,预留了三个按键,药品装载检测是通过一个轻触开关来实现的,也可以把他理解成一个按键。
按键的实际电路如下:

我们通常用的按键内部都是机械弹性开关,当它按下弹起的时候,机械触点会因为弹性作用而在闭合和断开的瞬间伴随着一连串的抖动。这种抖动会导致输入信号在高低电位之间弹跳,产生不正确的输入。 这里面电阻的作用是限流(害怕初学者不小心给设置成推挽输出了),在这里要注意的是要在芯片内部设置一个下拉(电路图上是没有加下拉电阻得到)。电容作用是硬件去抖,不过软件上还是需要软件消抖,硬件去抖只能改善不能消除,所以在有一些批量电路中,这个电容都是可以省去的,毕竟还是省不了软件消抖的。
轻触开关的实际电路如下:

在这里,我又要安利一波RT-Thread的软件包的,可以在RT-Thread软件包里面,搜索button,可以看到是有很多按键的软件包,这里就选择MultiButton了。用ENV工具把他添加到工程里面就可以了。参考他自带的example建立线程就可以轻松实现按键检测的,按下,弹起,单击,双击,长按等事件了:
#include < rtthread.h > #include < rtdevice.h > #include #include "multi_button.h" #include "bsp_beep.h" static struct button btn1; static struct button btn2; static struct button btn3; #define KEY1_PIN GET_PIN(G, 11) #define KEY2_PIN GET_PIN(G, 13) #define KEY3_PIN GET_PIN(B, 3) static uint8_t button1_read_pin(void) { return rt_pin_read(KEY1_PIN); } static uint8_t button2_read_pin(void) { return rt_pin_read(KEY2_PIN); } static uint8_t button3_read_pin(void) { return rt_pin_read(KEY3_PIN); } void button1_callback(void *btn) { uint32_t btn_event_val; btn_event_val = get_button_event((struct button *)btn); switch (btn_event_val) { case PRESS_DOWN: rt_kprintf("button1 press downn"); break; case PRESS_UP: rt_kprintf("button1 press upn"); break; case PRESS_REPEAT: rt_kprintf("button1 press repeatn"); break; case SINGLE_CLICK: beep(20); rt_kprintf("button1 single clickn"); break; case DOUBLE_CLICK: rt_kprintf("button1 double clickn"); break; case LONG_PRESS_START: rt_kprintf("button1 long press startn"); break; case LONG_PRESS_HOLD: rt_kprintf("button1 long press holdn"); break; } } void button2_callback(void *btn) { uint32_t btn_event_val; btn_event_val = get_button_event((struct button *)btn); switch (btn_event_val) { case PRESS_DOWN: rt_kprintf("button2 press downn"); break; case PRESS_UP: rt_kprintf("button2 press upn"); break; case PRESS_REPEAT: rt_kprintf("button2 press repeatn"); break; case SINGLE_CLICK: beep(20); rt_kprintf("button2 single clickn"); break; case DOUBLE_CLICK: rt_kprintf("button2 double clickn"); break; case LONG_PRESS_START: rt_kprintf("button2 long press startn"); break; case LONG_PRESS_HOLD: rt_kprintf("button2 long press holdn"); break; } } void button3_callback(void *btn) { uint32_t btn_event_val; btn_event_val = get_button_event((struct button *)btn); switch (btn_event_val) { case PRESS_DOWN: rt_kprintf("button3 press downn"); break; case PRESS_UP: rt_kprintf("button3 press upn"); break; case PRESS_REPEAT: rt_kprintf("button3 press repeatn"); break; case SINGLE_CLICK: beep(20); rt_kprintf("button3 single clickn"); break; case DOUBLE_CLICK: rt_kprintf("button3 double clickn"); break; case LONG_PRESS_START: rt_kprintf("button3 long press startn"); break; case LONG_PRESS_HOLD: rt_kprintf("button3 long press holdn"); break; } } void btn_thread_entry(void *p) { while (1) { /* 5ms */ rt_thread_delay(RT_TICK_PER_SECOND / 200); button_ticks(); } } int multi_button_test(void) { rt_thread_t thread = RT_NULL; /* Create background ticks thread */ thread = rt_thread_create("btn", btn_thread_entry, RT_NULL, 2048, 20, 10); if (thread == RT_NULL) { return RT_ERROR; } rt_thread_startup(thread); /* low level drive */ rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */ button_init(&btn1, button1_read_pin, PIN_HIGH); button_attach(&btn1, PRESS_DOWN, button1_callback); button_attach(&btn1, PRESS_UP, button1_callback); button_attach(&btn1, PRESS_REPEAT, button1_callback); button_attach(&btn1, SINGLE_CLICK, button1_callback); button_attach(&btn1, DOUBLE_CLICK, button1_callback); button_attach(&btn1, LONG_PRESS_START, button1_callback); button_attach(&btn1, LONG_PRESS_HOLD, button1_callback); button_start(&btn1); rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */ button_init(&btn2, button2_read_pin, PIN_HIGH); button_attach(&btn2, PRESS_DOWN, button2_callback); button_attach(&btn2, PRESS_UP, button2_callback); button_attach(&btn2, PRESS_REPEAT, button2_callback); button_attach(&btn2, SINGLE_CLICK, button2_callback); button_attach(&btn2, DOUBLE_CLICK, button2_callback); button_attach(&btn2, LONG_PRESS_START, button2_callback); button_attach(&btn2, LONG_PRESS_HOLD, button2_callback); button_start(&btn2); rt_pin_mode(KEY3_PIN, PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */ button_init(&btn3, button3_read_pin, PIN_HIGH); button_attach(&btn3, PRESS_DOWN, button3_callback); button_attach(&btn3, PRESS_UP, button3_callback); button_attach(&btn3, PRESS_REPEAT, button3_callback); button_attach(&btn3, SINGLE_CLICK, button3_callback); button_attach(&btn3, DOUBLE_CLICK, button3_callback); button_attach(&btn3, LONG_PRESS_START, button3_callback); button_attach(&btn3, LONG_PRESS_HOLD, button3_callback); button_start(&btn3); return RT_EOK; } INIT_APP_EXPORT(multi_button_test);
不想搞这么复杂,就只是单独想检测一下药物有没有放好的话也可以用最简单的延时来消除这个按键按下的抖动。像下面这个一样:
static void button_scan(void *arg) { while (1) { rt_thread_mdelay(50); if (button_key0_read() == 1) { rt_thread_mdelay(50); if (button_key0_read() == 1) { medicine_state = 1; } } else { medicine_state = 0; } } } 审核编辑 黄宇
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
检测
+关注
关注
5文章
4930浏览量
94286 -
RT-Thread
+关注
关注
32文章
1638浏览量
45206
发布评论请先 登录
相关推荐
热点推荐
立创·梁山派开发板-21年电赛F题-送药小车-K210功能实现代码讲解
关键的注释都添加了,可以帮助理解代码,这段代码同时实现了寻红线和数字识别,但是还做不到同时运行,在寻红线的时候没法数字识别,这两个状态之间的切换可以通过长按K210上的用户按键或者由立创
开发板-21年电赛F题-送药小车-小车寻红线环的调试与实现
PID控制来说,测量值是红线相较屏幕中线的偏移,目标值是想让红线偏移为0,输出值是电机的速度。
根据14_立创梁山派与K210串口通信协议框架搭建.md文档我们的
立创·梁山派开发板-21年电赛F题-送药小车实现思路
基本要求
1. 根据走廊上的标识信息自动识别,寻径将药品送到指定病房,投影要在门口区域内,
2. 到了指定病房后,点亮红色指示灯,等待卸载药品。
3. 人工卸掉药品后,小车自动熄灭红色指示灯,开始返回。
4. 自动返回药房,点亮绿色指示灯。
VHDL—按键消抖
达到去抖动的目的。本例中用状态机实现了消抖电路:端口描述:clk 输入检测时钟;reset 复位信号;din 原始按键信号输入; dout
发表于 11-11 17:17
•2次下载
立创梁山派开发板-21年电赛F题-送药小车-小车角度环的调试与实现
来达到目标值。
第二种是在实现小车轮子位置环的基础上,控制两边轮子同时向不同的方向旋转一定的圈数(编码器脉冲),在小车轮子不打滑的情况下转过的角度就是一个确定的值,在送药
立创·梁山派开发板-21年电赛F题-送药小车-与K210串口通信协议框架搭建
在K210可以识别到色块和识别数字后,就需要把这些信息传递给立创梁山派了。而立创梁山派也需要控制
立创·梁山派开发板-21年电赛F题-送药小车数据的发布与订阅
推荐或不建议使用全局变量来传递信息的原因主要有以下几点:
1. 竞争条件:在多任务环境下,全局变量会面临竞争条件的问题。当多个任务同时读写同一个全局变量时,会导致数据的不一致性和错误的结果。这是因为任务的执行是并发的,无法控制它们的执行顺序。
2. 数据共享和保护:全局变量被所有任务共享,这意味着多个任务可以同时访问和修改该变量。如果没有正确的数据保护机制,可能会导致数据损坏或冲突。
3. 可维护性和调试困难:使用全局变量传递信息可能导致代码的可维护性和调试的困难。由于全局变量可以被任何任务修改,追踪问题的根源和调试错误可能会变得更加困难。
如何在FPGA中实现按键消抖
在FPGA(现场可编程门阵列)中实现按键消抖是一个重要的设计环节,特别是在处理用户输入时,由于物理按键的机械特性和电气特性,
立创梁山派-21年电赛F题-智能送药小车-按键检测的消抖和实现
评论