本帖最后由 海洋无限 于 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闪烁。最后看下实验效果图片,分别为非数字键和数字键的情况
|