前言
根据本文教程开始之前,需要先将LVGL成功移植到STM32项目中,可以参考网上的教程进行LVGL移植操作,也可以参考我之前整理的这篇:
基于STM32实现LVGL移植、显示(LVGL版本8.3.10)
配置输入接口
lv_port_indev.c和lv_port_indev.h是LVGL输入设备移植文件,将这两个文件中的#if 0修改为#if 1来使能对应的输入设备功能。
将文件中包含的头文件路径修正为:#include "lv_port_indev.h"和#include "lvgl.h"
可以看到文件中有很多接口,分为以下几类:
touchpad:用于触摸屏相关。
mouse:用于鼠标相关。
keypad:用于键盘/按键矩阵相关。
encoder:用于编码器相关。
button:用于外部按键相关。
lv_port_indev_init()函数中有很多设备初始化,我们用哪些功能就留着哪些,其余的可以全部注释。比如我只用触摸屏相关的,其余的可以先暂时注释掉,后续用哪个开哪个:
void lv_port_indev_init(void) { /** * Here you will find example implementation of input devices supported by LittelvGL: * - Touchpad * - Mouse (with cursor support) * - Keypad (supports GUI usage only with key) * - Encoder (supports GUI usage only with: left, right, push) * - Button (external buttons to press points on the screen) * * The `..._read()` function are only examples. * You should shape them according to your hardware */ static lv_indev_drv_t indev_drv; /*------------------ * Touchpad * -----------------*/ /*Initialize your touchpad if you have*/ touchpad_init(); /*Register a touchpad input device*/ lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = touchpad_read; indev_touchpad = lv_indev_drv_register(&indev_drv); #if 0 /*------------------ * Mouse * -----------------*/ /*Initialize your mouse if you have*/ mouse_init(); /*Register a mouse input device*/ lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = mouse_read; indev_mouse = lv_indev_drv_register(&indev_drv); /*Set cursor. For simplicity set a HOME symbol now.*/ lv_obj_t * mouse_cursor = lv_img_create(lv_scr_act()); lv_img_set_src(mouse_cursor, LV_SYMBOL_HOME); lv_indev_set_cursor(indev_mouse, mouse_cursor); /*------------------ * 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);`*/ /*------------------ * Encoder * -----------------*/ /*Initialize your encoder if you have*/ encoder_init(); /*Register a encoder input device*/ lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_ENCODER; indev_drv.read_cb = encoder_read; indev_encoder = 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_encoder, group);`*/ /*------------------ * Button * -----------------*/ /*Initialize your button if you have*/ button_init(); /*Register a button input device*/ lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_BUTTON; indev_drv.read_cb = button_read; indev_button = lv_indev_drv_register(&indev_drv); /*Assign buttons to points on the screen*/ static const lv_point_t btn_points[2] = { {10, 10}, /*Button 0 -> x:10; y:10*/ {40, 100}, /*Button 1 -> x:40; y:100*/ }; lv_indev_set_button_points(indev_button, btn_points); #endif }对接触摸屏
进入lv_port_indev.c文件
开启lv_port_indev_init()中关于触摸的相关功能(Touchpad):
/*Initialize your touchpad if you have*/ touchpad_init(); /*Register a touchpad input device*/ lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = touchpad_read; indev_touchpad = lv_indev_drv_register(&indev_drv);touchpad_is_pressed()函数用于返回屏幕是否被按下,在这里可以对接我们的实际按下情况来返回true(按下)和false(未按下)。
/*Return true is the touchpad is pressed*/ static bool touchpad_is_pressed(void) { /*Your code comes here*/ return false; }touchpad_get_xy()函数用于获取屏幕坐标,在这里面对接获取屏幕坐标的相关内容。
/*Get the x and y coordinates if the touchpad is pressed*/ static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y) { /*Your code comes here*/ (*x) = 0; (*y) = 0; }对接Keypad键盘
进入lv_port_indev.c文件
开启lv_port_indev_init()中关于Keypad键盘的相关功能(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);LVGL 会不断调用keypad_read这个函数,观察keypad_read函数可以看出该函数通过调用keypad_get_key()返回的数值映射成对应的状态:
static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { static uint32_t last_key = 0; /*Get the current x and y coordinates*/ // mouse_get_xy(&data->point.x, &data->point.y); /*Get whether the a key is pressed and save the pressed key*/ uint32_t act_key = keypad_get_key(); if(act_key != 0) { >enum { LV_KEY_UP = 17, /*0x11*/ LV_KEY_DOWN = 18, /*0x12*/ LV_KEY_RIGHT = 19, /*0x13*/ LV_KEY_LEFT = 20, /*0x14*/ LV_KEY_ESC = 27, /*0x1B*/ LV_KEY_DEL = 127, /*0x7F*/ LV_KEY_BACKSPACE = 8, /*0x08*/ LV_KEY_ENTER = 10, /*0x0A, '\n'*/ LV_KEY_NEXT = 9, /*0x09, '\t'*/ LV_KEY_PREV = 11, /*0x0B, '*/ LV_KEY_HOME = 2, /*0x02, STX*/ LV_KEY_END = 3, /*0x03, ETX*/ };所以我们只需要修改keypad_get_key和keypad_read使keypad_read能根据我们的按键返回实际的效果即可。
测试
测试触摸接口
之前以及移植好LVGL和显示功能了,所以以下两个初始化应该已经调用了:
lv_init(); // LVGL初始化 lv_port_disp_init(); // 显示接口初始化添加输入设备初始化:
lv_port_indev_init(); // 输入接口初始化可以写一个测试demo,初始化后调用该demo即可验证是否支持触摸了。如:
static void btn_event_cb(lv_event_t *e) { lv_event_code_t code = lv_event_get_code(e); lv_obj_t *btn = lv_event_get_target(e); lv_obj_t *label = lv_obj_get_child(btn, 0); if (code == LV_EVENT_PRESSING) { // 按住时变红 lv_obj_set_style_bg_color(btn, lv_palette_main(LV_PALETTE_RED), 0); lv_label_set_text(label, "Pressing"); } else if (code == LV_EVENT_RELEASED) { // 松开恢复蓝色 lv_obj_set_style_bg_color(btn, lv_palette_main(LV_PALETTE_BLUE), 0); lv_label_set_text(label, "Press Me"); } } void lv_touch_test_demo(void) { lv_obj_t *btn = lv_btn_create(lv_scr_act()); lv_obj_set_size(btn, 120, 60); lv_obj_center(btn); // 默认蓝色 lv_obj_set_style_bg_color(btn, lv_palette_main(LV_PALETTE_BLUE), 0); // 同时监听多个事件 lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL); lv_obj_t *label = lv_label_create(btn); lv_label_set_text(label, "Press Me"); lv_obj_center(label); }我的测试方法和成功效果:
void StartTask06_LVGL(void const *argument) { /* USER CODE BEGIN StartTask06_LVGL */ lv_init(); // LVGL初始化 lv_port_disp_init(); // 显示接口初始化 lv_port_indev_init(); // 输入接口初始化 lv_touch_test_demo(); /* Infinite loop */ for (;;) { lv_task_handler(); osDelay(1); } /* USER CODE END StartTask06_LVGL */ }