• 说明
  • LV_INDEV_TYPE_BUTTON的使用
  • LV_INDEV_TYPE_KEYPAD的使用

说明

本实验使用LVGL版本为v9.2

LVGL中有四种输入设备,如下

LV_INDEV_TYPE_POINTER, /**< Touch pad, mouse, external button*/

LV_INDEV_TYPE_KEYPAD, /**< Keypad or keyboard*/

LV_INDEV_TYPE_BUTTON, /**< External (hardware button) which is assigned to a specific point of the screen*/

LV_INDEV_TYPE_ENCODER, /**< Encoder with only Left, Right turn and a Button*/

这里只记录LV_INDEV_TYPE_KEYPAD和LV_INDEV_TYPE_BUTTON的使用。因为这两个输入设备都可以用实体按键实现。当然,这两个输入设备掌握了,LV_INDEV_TYPE_ENCODER也是很容易类推的。

LV_INDEV_TYPE_BUTTON的使用

此输入设备其实是模拟的 LV_INDEV_TYPE_POINTER设备相应坐标被按下。使用它之前,应该有明确UI的布局,特别屏幕上按钮的坐标是明确的。

  1. 实体按键初始化
void key_init(void)
{// 配置 GPIOgpio_config_t io_conf = {.pin_bit_mask = (1ULL << KEY1)|(1ULL << KEY2)|(1ULL << KEY3),   // 选择 GPIO.mode = GPIO_MODE_INPUT,              // 设置为输出模式.pull_up_en = GPIO_PULLUP_ENABLE,     // 启用上拉.pull_down_en = GPIO_PULLDOWN_DISABLE, // 不启用下拉.intr_type = GPIO_INTR_DISABLE         // 不启用中断};gpio_config(&io_conf);
}
  1. 按键匹配键值

此键值将对应一个数组的序号,此数组是由BUTTON控件的坐标构成。

源码如下:

static int read_key(void)
{if(gpio_get_level(KEY1)==0){return 0;}if(gpio_get_level(KEY2)==0){return 1;}if(gpio_get_level(KEY3)==0){return 2;}	return -1;	
}
  1. 读取键值并保存到lv_indev_data_t数据结构中

目的是将实体按键与LVGL建立联系,后面通过创建输入设备相关API完成建立

void button_read(lv_indev_t * drv, lv_indev_data_t*data){static uint32_t last_btn = 0;   /*Store the last pressed button*/int btn_pr = read_key();     /*Get the ID (0,1,2...) of the pressed button*/if(btn_pr >= 0) {     /*Is there a button press? (E.g. -1 indicated no button was pressed)*/data->state = LV_INDEV_STATE_PRESSED;  /*Set the pressed state*/last_btn = btn_pr;   /*Save the ID of the pressed button*/} else {data->state = LV_INDEV_STATE_RELEASED; /*Set the released state*/}data->btn_id = last_btn;            /*Save the last button*/
}
  1. 创建输入设备
lv_indev_t * button_indev_drv;
button_indev_drv=lv_indev_create();
lv_indev_set_type(button_indev_drv,LV_INDEV_TYPE_BUTTON);//将输入设备设置为BUTTON模式
lv_indev_set_read_cb(button_indev_drv, button_read);//注册回调函数,即上一步实现的函数,这样就完成了硬件和LVGL的联系
//配置坐标点
static const lv_point_t btn_points[5] = {{0, 0},   /*当键值为0时模拟点击的坐标*/{80, 0},   /*当键值为1时模拟点击的坐标*/{160, 1},   /*当键值为2时模拟点击的坐标*/{320, 120},   /*当键值为3时模拟点击的坐标*/{160, 240},   /*当键值为4时模拟点击的坐标*/
};
lv_indev_set_button_points(button_indev_drv, btn_points);//将按键与坐标连接
  1. 使用LVGL的API在界面上创建三个BUTTON控件
	lv_obj_t * btn1;btn1 = lv_button_create(scr);lv_obj_set_width(btn1,80);lv_obj_set_height(btn1,35);lv_obj_set_pos(btn1,0,0);/*Button event*/lv_obj_add_event_cb(btn1, btn_event_handler, LV_EVENT_ALL, NULL);lv_obj_add_flag(btn1, LV_OBJ_FLAG_CHECKABLE);lv_obj_t * lbl1 = lv_label_create(btn1);lv_label_set_text_static(lbl1, "LEFT");lv_obj_align(lbl1, LV_ALIGN_CENTER,0, 0);lv_obj_t * btn2;btn2 = lv_button_create(scr);lv_obj_set_width(btn2,80);lv_obj_set_height(btn2,35);lv_obj_set_pos(btn2,80,0);/*Button event*/lv_obj_add_event_cb(btn2, btn_event_handler, LV_EVENT_ALL, NULL);lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);lv_obj_t * lbl2 = lv_label_create(btn2);lv_label_set_text_static(lbl2, "RIGHT");lv_obj_t * btn3;btn3 = lv_button_create(scr);lv_obj_set_width(btn3,80);lv_obj_set_height(btn3,35);lv_obj_set_pos(btn3,0,70);/*Button event*/lv_obj_add_event_cb(btn3, btn_event_handler, LV_EVENT_ALL, NULL);lv_obj_add_flag(btn3, LV_OBJ_FLAG_CHECKABLE);lv_obj_t * lbl3 = lv_label_create(btn3);lv_label_set_text_static(lbl3, "DOWN");lv_obj_align(lbl3, LV_ALIGN_CENTER,0, 0);
  1. 创建群组,并将输入设备绑定到群组且将以上三个BUTTON加入
	lv_group_t *g = lv_group_create();lv_indev_set_group(button_indev_drv, g); //绑定定义的lv_indev_t lv_group_add_obj(g ,btn1);lv_group_add_obj(g ,btn2);lv_group_add_obj(g ,btn3);

此时按下实体按键将会控制对应BUTTON控件按下。

  1. 此时可以创建BUTTON回调函数了
void btn_event_handler(lv_event_t *e)//按键回调函数
{lv_event_code_t code = lv_event_get_code(e);if(code == LV_EVENT_CLICKED) {ESP_LOGI(TAG,"Clicked");}
}

LV_INDEV_TYPE_KEYPAD的使用

LV_INDEV_TYPE_KEYPAD的键值LVGL已经有实现,固定死了。

LV_KEY_NEXT 专注于下一个对象
LV_KEY_PREV 专注于上一个对象
LV_KEY_ENTER 触发器 LV_EVENT_PRESSED/CLICKED/LONG_PRESSED 等事件
LV_KEY_UP 增加值或向上移动
LV_KEY_DOWN 减小值或向下移动
LV_KEY_RIGHT 增加值或向右移动
LV_KEY_LEFT 减小值或向左移动
LV_KEY_ESC 关闭或退出(例如,关闭下拉列表)
LV_KEY_DEL 删除(例如,“ 文本”区域中右侧的字符)
LV_KEY_BACKSPACE 删除左侧的字符(例如,在文本区域中)
LV_KEY_HOME 转到开头/顶部(例如,在“ 文本”区域中)
LV_KEY_END 转到末尾(例如,在“ 文本”区域中)

LV_INDEV_TYPE_KEYPAD按键分两个状态,导航态和编辑态。导航态就是在同组中选择相关控件,编辑态就是对控件数值上的增加/减少。LV_KEY_NEXT/PREV、LV_KEY_ENTER则是作为导航态。LV_KEY_UP/DOWN/LEFT/RIGHT则可以对控件进行数值上的编辑,一般而言LEFT/RIGHT就足够使用了。

LV_INDEV_TYPE_KEYPAD只需要对上面的代码做一些简单的调整,如下:

  1. 键值匹配
static int read_key(void)
{if(gpio_get_level(KEY1)==0){return LV_KEY_NEXT;}if(gpio_get_level(KEY2)==0){return LV_KEY_RIGHT;}if(gpio_get_level(KEY3)==0){return LV_KEY_LEFT;}	return -1;	
}
  1. 输入设备的回调函数
void button_read(lv_indev_t * drv, lv_indev_data_t*data){static uint32_t last_btn = 0;   /*Store the last pressed button*/int btn_pr = read_key();     /*Get the ID (0,1,2...) of the pressed button*/if(btn_pr >= 0) {     /*Is there a button press? (E.g. -1 indicated no button was pressed)*/data->state = LV_INDEV_STATE_PRESSED;  /*Set the pressed state*/last_btn = btn_pr;   /*Save the ID of the pressed button*/} else {data->state = LV_INDEV_STATE_RELEASED; /*Set the released state*/}
//注意这个地方做了修改data->key = last_btn;            /*Save the last button*/
}
  1. 创建输入设备
lv_indev_t * button_indev_drv;
button_indev_drv=lv_indev_create();
lv_indev_set_type(button_indev_drv,LV_INDEV_TYPE_KEYPAD);//将输入设备设置为KEYPAD模式
lv_indev_set_read_cb(button_indev_drv, button_read);//注册回调函数,即上一步实现的函数,这样就完成了硬件和LVGL的联系
  1. 按键回调函数

既然编辑态会有值的变化,那自然会触发相关事件,所以有了下面的改变

void btn_event_handler(lv_event_t *e)//按键回调函数
{lv_event_code_t code = lv_event_get_code(e);
//LV_EVENT_CLICKED这个事件在KEYPAD中只有ENTER才会触发if(code == LV_EVENT_CLICKED) {ESP_LOGI(TAG,"Clicked");}else if(code == LV_EVENT_VALUE_CHANGED) {ESP_LOGI(TAG,"BUTTUN");}
}
  1. 只是按键不太能看到效果,可以创建一个slider加入组中,通过导航按键选中后,用LEFT/RIGHT进行编辑
	lv_obj_t *slider1;slider1=lv_slider_create(scr);lv_obj_set_pos(slider1,0,140);lv_group_add_obj(g ,slider1);

总结

经过以上编程后,其实LV_INDEV_TYPE_ENCODER也是很容易实现的,只要将左右旋转和按下动作对应LV_KEY_LEFT/RIGHT以及LV_KEY_ENTER,剩下的代码基本都差不多了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/91122.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/91122.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/91122.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++:STL中list的使用和模拟实现

C中的list是标准模板库&#xff08;STL&#xff09;提供的双向链表容器&#xff0c;支持高效的元素插入和删除操作。在上一篇中讲解了vector的使用和模拟实现&#xff0c;vector是具有连续的空间&#xff0c;迭代器是可以随机的&#xff0c;而list却于vector不同&#xff0c;li…

【编号58-61】我国四大高原矢量示意图shp数据

今天分享的是&#xff1a;中国四大高原&#xff0c;分别是青藏高原、内蒙古高原、黄土高原、云贵高原。青藏高原位置与范围&#xff1a;位于中国西南部&#xff0c;包括西藏、青海的全部&#xff0c;川西高原及滇西北高原等部分地区。它的边界&#xff0c;向东是横断山脉&#…

【AI落地应用实战】利用 Amazon Bedrock Claude3 打造个性化 AI Character 应用

目录一、引言&#xff1a;AI Character应用的市场前景与技术基础二、技术架构设计2.1、整体方案概述2.2、核心组件介绍2.3、部署架构图三、系统部署方案3.1、方案总述3.2、实践流程1️⃣. Bedrock 配置2️⃣. 安装 SillyTavern3️⃣. 配置 SillyTavern 使用 Claude3 模型4️⃣.…

Java常用日志框架介绍

Java提供了很多第三方的日志框架可供使用&#xff0c;按照现在的设计理念&#xff0c;一般把日志框架分成门面(Facade)部分和具体实现(Implementation)部分&#xff0c;门面(Facade)提供了抽象的api规范&#xff0c;实现(Implementation)负责实现api完成具体的日志记录功能。开…

飞书 —— 多维表格 —— AI生成

1.添加关联账号&#xff1a; 2.获取密钥 ARK_API_KEY 进入火山引擎服务页面&#xff1a;https://console.volcengine.com/ark/region:arkcn-beijing/model/detail?Iddeepseek-r1 先进入推理模型 > 快捷API接入 再去在线推理中创建推理接入点 点击新创建好的接入点的API调…

我的世界模组开发教程——资源(1)

下面我们来研究一下ResourceLocation,每次开启游戏时都会报这个错误:“ResourceLocation 中的 ResourceLocation(String) 已过时, 且标记为待删除”,下面我们来详细的研究一下这个类 ResourceLocation ResourceLocation 是 Minecraft 中用于唯一标识游戏资源的核心类(如方…

我从 Web2 转型到 Web3 的 9 条经验总结

作者&#xff1a;Forte Group 高级区块链工程师 Yurii Kovalchuk原文&#xff1a;https://cryptoslate.com/why-i-left-web2-for-web3-and-why-you-might-too/三年前&#xff0c;我做出了一个彻底改变职业轨迹的决定&#xff1a;离开熟悉的 Web2&#xff0c;投身于深邃、混乱却…

【MySQL 数据库】MySQL索引特性(一)磁盘存储定位扇区InnoDB页

文章目录没有索引&#xff0c;可能会有什么问题二、认识磁盘2.1 MySQL与存储2.2 磁盘&#xff1a;2.3 扇区2.4 定位扇区2.5 结论三、三者作用流程&#xff08;磁盘&#xff0c;块&#xff0c;InnoDB页&#xff09;四、MySQL与磁盘交互基本单位五、建立共识&#x1f6a9;总结没有…

2419. 按位与最大的最长子数组

Problem: 2419. 按位与最大的最长子数组 文章目录思路解题过程复杂度Code思路 按位异或只会让数值越来越小&#xff0c;因此最长的连续按位与的最大值只存在于连续最大值中。 解题过程 遍历数组取出最大值&#xff0c;再遍历找到每一次连续最大值&#xff0c;从中取出最长的连续…

基于Java(SpringBoot)+Vue+MySQL 实现(Web)的网络课程平台

基于 SpringBoot 的网络课程平台1 绪论1.1 引言本科题研究并实现了一个面向网络学习的平台&#xff0c;为需要学习的人提供了一个学习的平台。任何人都课在本平台进行注册登录&#xff0c;学习观看视频。本平台是一个关于网络课程学习平台&#xff0c;学员科自主选择视频学习&a…

Centos7 | 防火墙(firewalld)使用ipset管理ip地址的集合

文章目录一、firewalld中ipset的用途1.1 用途1.2 注意与iptables所用的ipset命令的不同&#xff0c;1.3 配置详解二、firewalld中ipset的操作例子2.1 新建一个set2.2 在set中添加ip2.3 从set中删除ip2.4 删除一个set2.5 打印一个set的文件路径2.6 打印一个set的内容2.8 判断一个…

Day06_C++编程

01.思维导图02.将鸟笼放飞所有鸟类的题&#xff0c;改成观察者模式#include <iostream> #include <cstring> #include <cstdlib> #include <unistd.h> #include <sstream> #include <vector> #include <memory>//写一个鸟类:有一个多…

【面试场景题】随机立减金额计算

文章目录背景设计思路方案结论高斯分布&#xff08;正态分布&#xff09;背景 某电商公司跟某银行有合作&#xff0c;推进银行信用卡办卡&流水&#xff0c;使用此银行信用卡用户&#xff0c;支付可以随机立减10&#xff5e;30元。其实公司每一笔都可获得30元支付立减金&…

2025年湖北中级注册安全工程师报考那些事

2025年湖北中级注册安全工程师报考那些事各位从事建筑安全的人员看过来&#xff0c;注册安全工程师是你们行业认可度较为高的证书。关于报考无论是安全相关专业跟不相关的专业都是可以报考的。只是年份要求不同。 本科&#xff1a;相关专业3年&#xff0c;不相关专业4年。 专科…

Prometheus + Grafana + Micrometer 监控方案详解

这套组合是当前Java生态中最流行的监控解决方案之一&#xff0c;特别适合云原生环境下的微服务应用监控。下面我将从技术实现到最佳实践进行全面解析。 一、技术栈组成与协作 1. 组件分工组件角色关键能力Micrometer应用指标门面(Facade)统一指标采集API&#xff0c;对接多种监…

实习小记(个人中心的编辑模块)

实习小记&#xff08;个人中心的编辑模块&#xff09; 项目需要加一个个人中心的编辑模块&#xff0c;也是差不多搞了一天下来&#xff0c;其中遇到了很多问题&#xff0c;也是来记录、分享一下。 技术栈&#xff1a;React、antd、TypeScript 需求 点击编辑&#xff0c;弹出编…

【7】串口编程三种模式(查询/中断/DMA)韦东山老师学习笔记(课程听不懂的话试着来看看我的学习笔记吧)

<1>前置概念补充在深入拆解三种模式前&#xff0c;先通过提供的 “函数对比表” 建立整体认知&#xff1a;这张表是串口收发的「武器库索引」&#xff0c;清晰标注了查询、中断、DMA 三种模式下&#xff0c;收发 / 回调函数的对应关系。后续会结合实际代码&#xff0c;讲…

【Kubernetes 指南】基础入门——Kubernetes 201(二)

二、滚动升级- 滚动升级&#xff08;Rolling Update&#xff09;通过逐个容器替代升级的方式来实现无中断的服务升级&#xff1a;- 在滚动升级的过程中&#xff0c;如果发现了失败或者配置错误&#xff0c;还可以随时回滚&#xff1a;- 需要注意的是&#xff0c; kubectl rolli…

网络资源模板--基于Android Studio 实现的图书商城App

目录 一、测试环境说明 二、项目简介 三、项目演示 四、部设计详情&#xff08;部分) 登录注册页 首页 五、项目源码 一、测试环境说明 电脑环境 Windows 11 编写语言 JAVA 开发软件 Android Studio (2020) 开发软件只要大于等于测试版本即可(近几年官网直接下载…

JavaWeb 进阶:Vue.js 与 Spring Boot 全栈开发实战(Java 开发者视角)

作为一名 Java 开发工程师&#xff0c;当你掌握了 HTML、CSS 和 JavaScript 的基础后&#xff0c;是时候接触现代前端框架了。Vue.js 以其简洁的 API、渐进式的设计和优秀的中文文档&#xff0c;成为众多 Java 开发者入门前端框架的首选。Vue.js 让你能快速构建响应式、组件化的…