最近因为工作,也在学习了一些关于LVGL的内容,整体环境目前是:一个单片机,外接一个屏幕,目前屏幕是已经点亮和有触摸;但还希望在这个为基础,增加一些按键控制的环节,比如上下左右,进入返回这些的操作,所以有了这篇文章;
此贴目的:基于LVGL V9版本,在驱动层注册键盘keypad,初始化,将想要的引脚接口配置好,读到他的GPIO电平,当按键被按下后,触发,然后再讲这个值传输到上层AP层,AP层的UI做出相对应的反应。
以下为驱动层方面的处理:
做一个整体去初始化设备的函数lv_port_indev_init,在这个函数中对keypad做初始化和注册键盘,读取键盘的处理;
C
void lv_port_indev_init(void)
{
//此处只用键盘初始化做示例,如果对其他IO设备有需求的话,也可以增加,例如:鼠标,encoder,touchpad等
keypad_init();
indev_keypad = lv_indev_create();
lv_indev_set_type(indev_keypad, LV_INDEV_TYPE_KEYPAD);
lv_indev_set_read_cb(indev_keypad, keypad_read);
}
后续在keypad初始化中,对想要的GPIO口进行相应的处理:
C
#define KEY_PIN1 "PD.2"
static void keypad_init(void)
{
static u32 pin = 0;
pin = gpio_pin_check(KEY_PIN1, GPIO_SET_MODE_FLAG);
rt_pin_mode(pin, PIN_MODE_INPUT_PULLUP);
rt_pin_attach_irq(pin, PIN_IRQ_MODE_RISING_FALLING,
gpio_input_irq_handler, &pin);
rt_pin_irq_enable(pin, PIN_IRQ_ENABLE);
}
当然,不可或缺的还有keypad_read
C
static void keypad_read(lv_indev_t * indev_drv, lv_indev_data_t * data)
{
static uint32_t last_key = 0;
/*Get whether the a key is pressed and save the pressed key*/
uint32_t act_key = keypad_get_key();
if(act_key != 0) {
data->state = LV_INDEV_STATE_PR;
/*Translate the keys to LVGL control characters according to your key definitions*/
switch(act_key) {
case 1:
act_key = LV_KEY_DOWN;
break;
case 2:
act_key = LV_KEY_UP;
break;
case 3:
act_key = LV_KEY_LEFT;
break;
case 4:
act_key = LV_KEY_RIGHT;
break;
case 5:
act_key = LV_KEY_ENTER;
break;
}
last_key = act_key;
}
else {
data->state = LV_INDEV_STATE_REL;
}
data->key = last_key;
}
随后的话,在get key的函数中也要做相对应的处理,实际上这些都是环环相扣的,初始化中会包含读,读中又包含获取,才能相对应上
C
/*Get the currently being pressed key. 0 if no key is pressed*/
static uint32_t keypad_get_key(void)
{
/*Your code comes here*/
static uint8_t last_key = 0;
uint8_t current_key = 0;
if (key_trigger == 1) {
key_trigger = 0;
current_key = 1;
}
if(current_key != 0) {
last_key = current_key;
return current_key;
}
return 0;
}
后续的话就是需要在应用层做处理,在keypad_read中已经把值返回到对应的LV_KEY_DOWN/LV_KEY_UP/LV_KEY_LEFT/LV_KEY_RIGHT,故在应用层中比较重要的就是需要去获取这个key,其中的步骤我们一步步来:
1、需要有一个lv_group_t *menu_group,并增加初始化;
C
static lv_group_t *menu_group;
void lv_init_group()
{
menu_group = lv_group_create();
lv_group_set_editing(menu_group, false);
lv_indev_set_group(indev_keypad,menu_group);
}
2、在你的组中增加obj,例如把btn加进这个group中;
C
lv_group_add_obj(menu_group,btn);
3、给你的btn增加需要动的操作,并且增加focus属性!(最重要,没有这个属性将不会有任何响应)
然后才是对这个focus进行移动,例如lv_group_focus_next
C
lv_obj_add_event_cb(btn, menu_key_cb, LV_EVENT_KEY, NULL);
lv_group_focus_obj(current_selected_btn); // 给当前选中的按钮增加focus
static void menu_key_cb(lv_event_t *e)
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t * target = lv_event_get_target(e);
printf("get_key :%d\n", event_code);
if (event_code == LV_KEY_LEFT)
{
lv_group_focus_next(menu_group);
}
}
4、最后就是大功告成,可以看到效果了!
总结:
整体的LVGL功能其实不难,但就是有几个需要注意的点,例如:必须把输入设备绑定 group、需要把按钮加入进group、按钮还需要增加focus、回调属性(类似qt的信号槽);