本人使用ESP-WROOM-32开发板学习lvgl时,手头没有触摸屏,只有使用实体按键操作界面,下面是arduino环境下,基于lvgl7.10实现的代码。
key.h文件
#ifndef _KEY_H__
#define _KEY_H__
#ifdef __cplusplus
#include "lvgl.h"
#include <Arduino.h>
extern lv_indev_t* lv_button_device_obj;
void Key_Init(void);
uint8_t Key_Scan(void);
bool my_key_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data);
void lv_port_indev_init(void);
#endif
#endif
key.c文件
#include "key.h"
lv_indev_t* lv_button_device_obj;
uint8_t keypin0 = 13;
uint8_t keypin1 = 12;
uint8_t keypin2 = 14;
uint8_t keypin3 = 27;
void Key_Init(void) //按键初始化,这里仅初始化四个IO,用于按键输入。
{
pinMode(keypin0, INPUT_PULLUP);
pinMode(keypin1, INPUT_PULLUP);
pinMode(keypin2, INPUT_PULLUP);
pinMode(keypin3, INPUT_PULLUP);
}
uint8_t Key_Scan(void)
{
if (digitalRead(keypin0) == LOW)
{
return 2;
}
else if (digitalRead(keypin1) == LOW)
{
return 3;
}
else if (digitalRead(keypin2) == LOW)
{
return 1;
}
else if (digitalRead(keypin3) == LOW)
{
return 4;
}
return 0;
}
bool my_key_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
{
static uint32_t last_key = 0;
uint8_t act_enc = Key_Scan();
if (act_enc != 0) {
data->state = LV_INDEV_STATE_PR;
switch (act_enc) {
case 1:
act_enc = LV_KEY_NEXT;
break;
case 2:
act_enc = LV_KEY_LEFT;
break;
case 3:
act_enc = LV_KEY_RIGHT;
break;
case 4:
act_enc = LV_KEY_ENTER;
break;
}
last_key = (uint32_t)act_enc;
}
else {
data->state = LV_INDEV_STATE_REL;
}
data->key = last_key;
return false;
}
void lv_port_indev_init(void)
{
Key_Init();
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_KEYPAD;
indev_drv.read_cb = my_key_read;
lv_button_device_obj = lv_indev_drv_register(&indev_drv);
}
main.cpp文件
#include "key.h"
#include <TFT_eSPI.h>
#include "lvgl_display.h"
#include <Arduino.h>
#include "lvgl.h"
TFT_eSPI tft = TFT_eSPI();
static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * 10];
#if USE_LV_LOG != 0
void my_print(lv_log_level_t level, const char * file, uint32_t line, const char * dsc)
{
Serial.printf("%s@%d->%s\r\n", file, line, dsc);
Serial.flush();
}
#endif
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
uint32_t w = (area->x2 - area->x1 + 1);
uint32_t h = (area->y2 - area->y1 + 1);
tft.startWrite();
tft.setAddrWindow(area->x1, area->y1, w, h);
tft.pushColors(&color_p->full, w * h, true);
tft.endWrite();
lv_disp_flush_ready(disp);
}
void setup()
{
Serial.begin(115200);
#if USE_LV_LOG != 0
lv_log_register_print_cb(my_print);
#endif
tft.begin();
tft.setRotation(0);
lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = 240;
disp_drv.ver_res = 240;
disp_drv.flush_cb = my_disp_flush;
disp_drv.buffer = &disp_buf;
lv_disp_drv_register(&disp_drv);
create_btn();
}
void create_btn(void)
{
lv_group_t * lvgl_btn_group = lv_group_create();
lv_indev_set_group(lv_button_device_obj, lvgl_btn_group);
lv_obj_t *lvgl_btn = lv_btn_create(lv_scr_act(), NULL);
lv_obj_align(lvgl_btn , NULL, LV_ALIGN_CENTER, 0, 0);
lv_obj_t *label = lv_label_create(lvgl_btn, NULL);
lv_label_set_text(label, "Button");
lv_group_add_obj(lvgl_btn_group, lvgl_btn); //将创建的按键加入组
}
void loop()
{
lv_task_handler();
vTaskDelay(10);
}
通过以上代码可以使用lvgl创建一个按键控件,并将实体按键与按键控件关联。
上述代码初始化了四个IO,他们分别关联了LV_KEY_NEXT,LV_KEY_LEFT,LV_KEY_RIGHT,LV_KEY_ENTER等功能,因此可以使用实体按键操作创建并加入lvgl_btn_group 的lvgl控件。