[综合信息] 【华大测评】+ 事件驱动按键+定时器

[复制链接]
1263|1
 楼主| 海洋无限 发表于 2020-10-2 15:45 | 显示全部楼层 |阅读模式
本帖最后由 海洋无限 于 2020-10-2 15:49 编辑

之前有看到论坛里发的一个事件驱动按键和定时器程序,正好趁着这个开发板做下移植,顺便学习下,先传下源代码文件(文件名字为了自己方便管理,我改了) button_timer.zip (3.91 KB, 下载次数: 27)
压缩档中有timer和button两个代码,定时器和按键是经常使用的资源,感兴趣的可以学习下
button支持单击、双击、连击等,定时器对不使用rtos的系统来说非常重要,且使用方便,先说下移植的思路,使用CPU硬件tick作为滴答时钟,在这个基础上可以创建很多个软时钟,定时回调即可。源文件中的按钮回调函数需要用户为每个按键的事件创建回调,由于事件这种操作可能更适用在rtos的系统中,对于没有rtos的系统,我们按键一般都采用设置标志并轮询的方式比较好,所以我这里测试的时候键入了按键有效标记部分,这样按键的回调函数中直接设置按钮按下标记即可,按键的操作在其他地方再处理即可,如下原来的button结构体:
  1. typedef struct button {
  2.     uint16_t ticks;
  3.     uint8_t  repeat       : 4;
  4.     uint8_t  event        : 4;
  5.     uint8_t  state        : 3;
  6.     uint8_t  debounce_cnt : 3;
  7.     uint8_t  active_level : 1;
  8.     uint8_t  button_level : 1;
  9.     uint8_t  (*hal_button_Level)(void);
  10.     BtnCallback  cb[number_of_event];
  11.     struct button* next;
  12. }button;
我加了按键有效标识后为
  1. typedef struct button {
  2.     uint16_t ticks;
  3.     uint8_t  repeat       : 4;
  4.     uint8_t  event        : 4;
  5.     uint8_t  state        : 3;
  6.     uint8_t  debounce_cnt : 3;
  7.     uint8_t  active_level : 1;
  8.     uint8_t  button_level : 1;
  9.     uint8_t  (*hal_button_Level)(void);
  10.     BtnCallback  cb[number_of_event];
  11.     struct button* next;
  12.   
  13.     uint8_t  KeyValueSingle     :1;
  14.     uint8_t  KeyValueDouble     :1;
  15.     uint8_t  KeyValueLongStart  :1;
  16.     uint8_t  KeyValueLongHold   :1;
  17.     uint8_t  KeyValueUp         :1;
  18.     uint8_t  KeyValueDown       :1;
  19.     uint8_t  KeyValueRepeat     :1;
  20. }button;
这样,所有按键的所有时间就可以采用一个回调函数了,回调函数中直接设置按钮有效标识,代码阅读性更强,当然我这里仅仅是为了测试这种方式。开发板有4个独立按键、9个矩阵按键,我的定义如下
  1. #define KEY_IO_TOTALNUM         (4)

  2. #define KEY_UP                               0x00
  3. #define KEY_DOWN                       0x01
  4. #define KEY_LEFT                             0x02
  5. #define KEY_RIGHT                     0x03

  6. #define KEYOUT_TOTALNUM                      (3)
  7. #define KEYIN_TOTALNUM                      (3)
  8. #define KEY_MATRIX_TOTALNUM     (KEYOUT_TOTALNUM*KEYIN_TOTALNUM)
  9. #define KEY_NUM_0               (0x00)
  10. #define KEY_NUM_1               (0x01)
  11. #define KEY_NUM_2               (0x02)
  12. #define KEY_NUM_3               (0x03)
  13. #define KEY_NUM_4               (0x04)
  14. #define KEY_NUM_5               (0x05)
  15. #define KEY_NUM_6               (0x06)
  16. #define KEY_NUM_7               (0x07)
  17. #define KEY_NUM_8               (0x08)



定时器:
定时器这块代码基本不要改,直接使用就行,可以直接初始化几种常用的定时器,如5ms 10ms 50ms   100ms   500ms   1s等,后面直接在对应的回调中添加要轮询的功能函数即可,如下是我定义的timer:
  1. timer_init(&timer5ms,     timer_5ms_callback,   TIMER_NORMAL_DELAY,   TIMER_5MS_PRELOAD); //5ms loop
  2.         timer_start(&timer5ms);  

  3.         timer_init(&timer100ms,   timer_100ms_callback, TIMER_NORMAL_DELAY,   TIMER_100MS_PRELOAD); //100ms loop
  4.         timer_start(&timer100ms);

  5.         timer_init(&timer500ms,   timer_500ms_callback, TIMER_NORMAL_DELAY,   TIMER_500MS_PRELOAD); //500ms loop
  6.         timer_start(&timer500ms);
  7.         
  8.         timer_init(&timer1s,      timer_1s_callback,    TIMER_NORMAL_DELAY,   TIMER_1S_PRELOAD); //1s delay
  9.         timer_start(&timer1s);
最后,timer的timer_loop函数需要放在while循环中不停的运行,timer_ticks函数需要放在cpu硬件tick中定时调用。上述按键的button_ticks函数放在5ms定时器callback中调用即可,到此定时器和按键函数基本完成,由于之前OLED已经驱动,所以实验测试如下4个单按键分别为KEY_UP 、KEY_DOWN、 KEY_LEFT、KEY_RIGHT,当按下时在OLED上show   “&” “%”  “<”   “>”
9个矩阵按键分别为数字    0~8
最后在100ms定时器中检测按钮标识是否有效,show对应的信息到OLED即可,代码实现不难,这里就不详细说了,button和timer的代码我已经添加附件,感兴趣的可以查看附件,顺便说下矩阵键盘我试了可以稳定检测到按键按下信息,不会无判断,官方例程应该是使用中断方式,所以受案到板边的时候会出现LED闪烁。最后看下实验效果图片,分别为非数字键和数字键的情况
1.png 3.png







zeshoufx 发表于 2020-10-2 16:54 | 显示全部楼层
谢谢分享【事件驱动按键+定时器】
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:永远忠于年轻时的梦想!

39

主题

539

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部