海洋无限 发表于 2020-10-2 15:45

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

本帖最后由 海洋无限 于 2020-10-2 15:49 编辑

之前有看到论坛里发的一个事件驱动按键和定时器程序,正好趁着这个开发板做下移植,顺便学习下,先传下源代码文件(文件名字为了自己方便管理,我改了)
压缩档中有timer和button两个代码,定时器和按键是经常使用的资源,感兴趣的可以学习下
button支持单击、双击、连击等,定时器对不使用rtos的系统来说非常重要,且使用方便,先说下移植的思路,使用CPU硬件tick作为滴答时钟,在这个基础上可以创建很多个软时钟,定时回调即可。源文件中的按钮回调函数需要用户为每个按键的事件创建回调,由于事件这种操作可能更适用在rtos的系统中,对于没有rtos的系统,我们按键一般都采用设置标志并轮询的方式比较好,所以我这里测试的时候键入了按键有效标记部分,这样按键的回调函数中直接设置按钮按下标记即可,按键的操作在其他地方再处理即可,如下原来的button结构体:
typedef struct button {
    uint16_t ticks;
    uint8_trepeat       : 4;
    uint8_tevent      : 4;
    uint8_tstate      : 3;
    uint8_tdebounce_cnt : 3;
    uint8_tactive_level : 1;
    uint8_tbutton_level : 1;
    uint8_t(*hal_button_Level)(void);
    BtnCallbackcb;
    struct button* next;
}button;我加了按键有效标识后为
typedef struct button {
    uint16_t ticks;
    uint8_trepeat       : 4;
    uint8_tevent      : 4;
    uint8_tstate      : 3;
    uint8_tdebounce_cnt : 3;
    uint8_tactive_level : 1;
    uint8_tbutton_level : 1;
    uint8_t(*hal_button_Level)(void);
    BtnCallbackcb;
    struct button* next;

    uint8_tKeyValueSingle   :1;
    uint8_tKeyValueDouble   :1;
    uint8_tKeyValueLongStart:1;
    uint8_tKeyValueLongHold   :1;
    uint8_tKeyValueUp         :1;
    uint8_tKeyValueDown       :1;
    uint8_tKeyValueRepeat   :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

谢谢分享【事件驱动按键+定时器】
页: [1]
查看完整版本: 【华大测评】+ 事件驱动按键+定时器