【前言】
RT-Spark开发板使用的LCD屏是不带触摸的,但是开发上板载了4个可供用户使用的按键,因此绑定这4个按键给LVGL做交互使用还是非常有必要的。以前还从来没有使用如何绑定,所以还是花费了一些时间进行学习,在这里做一下分享,一来方便以后查看,二来分享给有同样需求的朋友。
【硬件】
RT-Spark 星火一号开发板。
【软件】
1、RT-Thread.
2、MDK5.38
3、LVGL8.3
4、Gui-Guider。
【工程模版】
使用开发板的lvgl模版,在我前面帖子介绍的基础之上来添加功能。帖子链接为:STM32F407之GuiGuider界面移植-电子产品世界论坛 (eepw.com.cn)
【LVGL面板设计】
1、在gui_guider设计中,我添加了一个计数器的模板其界面如下:
在工程模版中,他的计数功能都已经实现好了,不在本文详细介绍,其功能就是单击两个按键,会对计数标签的数值进行加减,长按会连续的加减。
将它他生成的代码添加上一篇帖子的方法添加到工程中。就完成面板的设计工作。
【按键驱动】
按键的驱动,首先要找到原理图,找到对应的按键与MCU的连接PIN脚,以及按键按下时的电平状态。
其原理图如下所示:
从以上原理图看到,按键按下后,对地短接,低电平为按下。因此需要把按键配置为上拉输入模式。
新建bsp_kdy.c/h,并加添进工程之中,代码如下:
#include "bsp_key.h" #include "main.h" #include <rtthread.h> #include <rtdevice.h> #include "drv_gpio.h" #define PIN_BTN_UP GET_PIN(C, 5) #define PIN_BTN_DOWN GET_PIN(C, 1) #define PIN_BTN_LEFT GET_PIN(C, 0) #define PIN_BTN_RIGHT GET_PIN(C, 4) void key_init(void) { rt_pin_mode(PIN_BTN_UP, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PIN_BTN_DOWN, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PIN_BTN_LEFT, PIN_MODE_INPUT_PULLUP); rt_pin_mode(PIN_BTN_RIGHT, PIN_MODE_INPUT_PULLUP); } uint32_t bsp_get_key(void) { if (rt_pin_read(PIN_BTN_UP) == 0) { return 1; } else if (rt_pin_read(PIN_BTN_DOWN) == 0) { return 2; } else if (rt_pin_read(PIN_BTN_LEFT) == 0) { return 3; } else if (rt_pin_read(PIN_BTN_RIGHT) == 0) { return 5; } return 0xFF; }
同时在bsp_key.h中把init以及键值的获取开发接口:
#ifndef __BSP_KEY_H #define __BSP_KEY_H #include "stm32f4xx.h" void key_init(void); uint32_t bsp_get_key(void); #endif
【LVGL键盘接口】
键盘驱动在lv_port_indev.c中进行初始化与键盘的获取,先上代码:
/* * Copyright (c) 2006-2022, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2021-10-18 Meco Man The first version */ #include <lvgl.h> #include <rtdevice.h> #include "bsp_key.h" static void keypad_init(void); static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); uint32_t keypad_get_key(void); lv_indev_t * indev_keypad; void lv_port_indev_init(void) { static lv_indev_drv_t indev_drv; /*------------------ * Keypad * -----------------*/ /*Initialize your keypad or keyboard if you have*/ keypad_init(); /*Register a keypad input device*/ lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_KEYPAD; indev_drv.read_cb = keypad_read; indev_keypad = lv_indev_drv_register(&indev_drv); /*Later you should create group(s) with `lv_group_t * group = lv_group_create()`, *add objects to the group with `lv_group_add_obj(group, obj)` *and assign this input device to group to navigate in it: *`lv_indev_set_group(indev_keypad, group);`*/ } /*------------------ * Keypad * -----------------*/ /*Initialize your keypad*/ static void keypad_init(void) { key_init(); /*Your code comes here*/ } /*Will be called by the library to read the mouse*/ static void keypad_read(lv_indev_drv_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; rt_kprintf("act_key:%d",act_key); /*Translate the keys to LVGL control characters according to your key definitions*/ switch(act_key) { case 1: act_key = LV_KEY_NEXT; break; case 2: act_key = LV_KEY_PREV; 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 the currently being pressed key. 0 if no key is pressed*/ static uint32_t keypad_get_key(void) { /*Your code comes here*/ uint32_t key = bsp_get_key(); if(key!=0xFF) { return key; } return 0; }
代码分析:
1、这里的代码在lvgl的输入设备驱动中都是有的,我们需要自己实现的代码只需把按键初始化的驱动放到keypad_init里面进行按键的初始化。
2、键盘的获取,在keypad_get_key这个函数中,添加我们按键键盘的获取代码,就是将bsp_get_key的键盘反馈给lvgl的按键就行了:
到此按建获取的代码就移植完成。
【按键与控件的绑定】
按键与控制的绑定,我所需要用到lvgl的groups这个组件。
在custom自定义函数中,我创建了一个用groups,并将UI组件中的两个bnt添加进组件中,同时把铵键组也添加进去。
最后把这个初始化的函数添加进UI界初始化的函数中就行了。
【运行效果】
按上下键后可以切换按键,按下右键,可以进行计数的更新。
【总结】
LVGL提供了触摸、键盘、编码器等的接口,可以非常方便的选择多种输入设备进行用户的交互。
在学习绑定按键驱动中,学习了许多的教程,起先看起来非常复杂,但是经过自己实践之后,感觉就几步就行了。