打印
[综合信息]

【华大测评】+ 事件驱动按键+定时器

[复制链接]
1007|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 海洋无限 于 2020-10-2 15:49 编辑

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

#define KEY_UP                               0x00
#define KEY_DOWN                       0x01
#define KEY_LEFT                             0x02
#define KEY_RIGHT                     0x03

#define KEYOUT_TOTALNUM                      (3)
#define KEYIN_TOTALNUM                      (3)
#define KEY_MATRIX_TOTALNUM     (KEYOUT_TOTALNUM*KEYIN_TOTALNUM)
#define KEY_NUM_0               (0x00)
#define KEY_NUM_1               (0x01)
#define KEY_NUM_2               (0x02)
#define KEY_NUM_3               (0x03)
#define KEY_NUM_4               (0x04)
#define KEY_NUM_5               (0x05)
#define KEY_NUM_6               (0x06)
#define KEY_NUM_7               (0x07)
#define KEY_NUM_8               (0x08)



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

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

        timer_init(&timer500ms,   timer_500ms_callback, TIMER_NORMAL_DELAY,   TIMER_500MS_PRELOAD); //500ms loop
        timer_start(&timer500ms);
        
        timer_init(&timer1s,      timer_1s_callback,    TIMER_NORMAL_DELAY,   TIMER_1S_PRELOAD); //1s delay
        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闪烁。最后看下实验效果图片,分别为非数字键和数字键的情况








使用特权

评论回复
沙发
zeshoufx| | 2020-10-2 16:54 | 只看该作者
谢谢分享【事件驱动按键+定时器】

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

22

主题

415

帖子

1

粉丝