野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1237|回复: 0

立创梁山派-21年电赛F题-智能送药小车-按键检测的消抖和...

[复制链接]
发表于 2023-8-4 10:17:37 | 显示全部楼层 |阅读模式
送药小车代码仓库:https://gitee.com/lcsc/medical_car

更好的观看体验请去:https://lceda001.feishu.cn/wiki/ZDYbwqDfCiwVlckUEcScF0KSnRh

送药小车立创开源平台资料:https://oshwhub.com/li-chuang-kai-fa-ban/21-dian-sai-f-ti-zhi-neng-song-yao-xiao-che

购买链接:https://item.szlcsc.com/5810323.html


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

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

在这里,我又要安利一波RT-Thread的软件包的,可以在RT-Thread软件包里面,搜索button,可以看到是有很多按键的软件包,这里就选择MultiButton了。用ENV工具把他添加到工程里面就可以了。参考他自带的example建立线程就可以轻松实现按键检测的,按下,弹起,单击,双击,长按等事件了:
  1. #include <rtthread.h>
  2. #include <rtdevice.h>
  3. #include <board.h>
  4. #include "multi_button.h"
  5. #include "bsp_beep.h"

  6. static struct button btn1;
  7. static struct button btn2;
  8. static struct button btn3;

  9. #define KEY1_PIN GET_PIN(G, 11)
  10. #define KEY2_PIN GET_PIN(G, 13)
  11. #define KEY3_PIN GET_PIN(B, 3)

  12. static uint8_t button1_read_pin(void) { return rt_pin_read(KEY1_PIN); }
  13. static uint8_t button2_read_pin(void) { return rt_pin_read(KEY2_PIN); }
  14. static uint8_t button3_read_pin(void) { return rt_pin_read(KEY3_PIN); }

  15. void button1_callback(void *btn)
  16. {
  17.     uint32_t btn_event_val;

  18.     btn_event_val = get_button_event((struct button *)btn);

  19.     switch (btn_event_val)
  20.     {
  21.     case PRESS_DOWN:
  22.         rt_kprintf("button1 press down\n");
  23.         break;

  24.     case PRESS_UP:
  25.         rt_kprintf("button1 press up\n");
  26.         break;

  27.     case PRESS_REPEAT:
  28.         rt_kprintf("button1 press repeat\n");
  29.         break;

  30.     case SINGLE_CLICK:
  31.         beep(20);
  32.         rt_kprintf("button1 single click\n");
  33.         break;

  34.     case DOUBLE_CLICK:
  35.         rt_kprintf("button1 double click\n");
  36.         break;

  37.     case LONG_PRESS_START:
  38.         rt_kprintf("button1 long press start\n");
  39.         break;

  40.     case LONG_PRESS_HOLD:
  41.         rt_kprintf("button1 long press hold\n");
  42.         break;
  43.     }
  44. }
  45. void button2_callback(void *btn)
  46. {
  47.     uint32_t btn_event_val;

  48.     btn_event_val = get_button_event((struct button *)btn);

  49.     switch (btn_event_val)
  50.     {
  51.     case PRESS_DOWN:
  52.         rt_kprintf("button2 press down\n");
  53.         break;

  54.     case PRESS_UP:
  55.         rt_kprintf("button2 press up\n");
  56.         break;

  57.     case PRESS_REPEAT:
  58.         rt_kprintf("button2 press repeat\n");
  59.         break;

  60.     case SINGLE_CLICK:
  61.         beep(20);
  62.         rt_kprintf("button2 single click\n");
  63.         break;

  64.     case DOUBLE_CLICK:
  65.         rt_kprintf("button2 double click\n");
  66.         break;

  67.     case LONG_PRESS_START:
  68.         rt_kprintf("button2 long press start\n");
  69.         break;

  70.     case LONG_PRESS_HOLD:
  71.         rt_kprintf("button2 long press hold\n");
  72.         break;
  73.     }
  74. }
  75. void button3_callback(void *btn)
  76. {
  77.     uint32_t btn_event_val;

  78.     btn_event_val = get_button_event((struct button *)btn);

  79.     switch (btn_event_val)
  80.     {
  81.     case PRESS_DOWN:
  82.         rt_kprintf("button3 press down\n");
  83.         break;

  84.     case PRESS_UP:
  85.         rt_kprintf("button3 press up\n");
  86.         break;

  87.     case PRESS_REPEAT:
  88.         rt_kprintf("button3 press repeat\n");
  89.         break;

  90.     case SINGLE_CLICK:
  91.         beep(20);
  92.         rt_kprintf("button3 single click\n");
  93.         break;

  94.     case DOUBLE_CLICK:
  95.         rt_kprintf("button3 double click\n");
  96.         break;

  97.     case LONG_PRESS_START:
  98.         rt_kprintf("button3 long press start\n");
  99.         break;

  100.     case LONG_PRESS_HOLD:
  101.         rt_kprintf("button3 long press hold\n");
  102.         break;
  103.     }
  104. }

  105. void btn_thread_entry(void *p)
  106. {
  107.     while (1)
  108.     {
  109.         /* 5ms */
  110.         rt_thread_delay(RT_TICK_PER_SECOND / 200);
  111.         button_ticks();
  112.     }
  113. }

  114. int multi_button_test(void)
  115. {
  116.     rt_thread_t thread = RT_NULL;

  117.     /* Create background ticks thread */
  118.     thread = rt_thread_create("btn", btn_thread_entry, RT_NULL, 2048, 20, 10);
  119.     if (thread == RT_NULL)
  120.     {
  121.         return RT_ERROR;
  122.     }
  123.     rt_thread_startup(thread);

  124.     /* low level drive */
  125.     rt_pin_mode(KEY1_PIN,
  126.                 PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */
  127.     button_init(&btn1, button1_read_pin, PIN_HIGH);
  128.     button_attach(&btn1, PRESS_DOWN, button1_callback);
  129.     button_attach(&btn1, PRESS_UP, button1_callback);
  130.     button_attach(&btn1, PRESS_REPEAT, button1_callback);
  131.     button_attach(&btn1, SINGLE_CLICK, button1_callback);
  132.     button_attach(&btn1, DOUBLE_CLICK, button1_callback);
  133.     button_attach(&btn1, LONG_PRESS_START, button1_callback);
  134.     button_attach(&btn1, LONG_PRESS_HOLD, button1_callback);
  135.     button_start(&btn1);

  136.     rt_pin_mode(KEY2_PIN,
  137.                 PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */
  138.     button_init(&btn2, button2_read_pin, PIN_HIGH);
  139.     button_attach(&btn2, PRESS_DOWN, button2_callback);
  140.     button_attach(&btn2, PRESS_UP, button2_callback);
  141.     button_attach(&btn2, PRESS_REPEAT, button2_callback);
  142.     button_attach(&btn2, SINGLE_CLICK, button2_callback);
  143.     button_attach(&btn2, DOUBLE_CLICK, button2_callback);
  144.     button_attach(&btn2, LONG_PRESS_START, button2_callback);
  145.     button_attach(&btn2, LONG_PRESS_HOLD, button2_callback);
  146.     button_start(&btn2);

  147.     rt_pin_mode(KEY3_PIN,
  148.                 PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */
  149.     button_init(&btn3, button3_read_pin, PIN_HIGH);
  150.     button_attach(&btn3, PRESS_DOWN, button3_callback);
  151.     button_attach(&btn3, PRESS_UP, button3_callback);
  152.     button_attach(&btn3, PRESS_REPEAT, button3_callback);
  153.     button_attach(&btn3, SINGLE_CLICK, button3_callback);
  154.     button_attach(&btn3, DOUBLE_CLICK, button3_callback);
  155.     button_attach(&btn3, LONG_PRESS_START, button3_callback);
  156.     button_attach(&btn3, LONG_PRESS_HOLD, button3_callback);
  157.     button_start(&btn3);

  158.     return RT_EOK;
  159. }
  160. INIT_APP_EXPORT(multi_button_test);
复制代码

不想搞这么复杂,就只是单独想检测一下药物有没有放好的话也可以用最简单的延时来消除这个按键按下的抖动。像下面这个一样:

static void button_scan(void *arg)
  1. <pre class="ace-line ace-line old-record-id-PlC2d4o2MoGgXPxYv9Lc88BdnRh"><code class="language-C" data-wrap="false">
  2. <div>{
  3.     while (1)
  4.     {
  5.         rt_thread_mdelay(50);
  6.         if (button_key0_read() == 1)
  7.         {
  8.             rt_thread_mdelay(50);
  9.             if (button_key0_read() == 1)
  10.             {
  11.                 medicine_state = 1;
  12.             }
  13.         }
  14.         else
  15.         {
  16.             medicine_state = 0;
  17.         }
  18.     }
  19. }</div></code></pre><div class="ace-line ace-line old-record-id-Hb4CdY0S0oZkodx9UP2crvtQn7b"></div>
复制代码



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-22 05:00 , Processed in 0.032811 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表