当前位置: 首页 > article >正文

告别触摸屏!用旋转编码器给STM32+LVGL项目做个复古又实用的物理菜单

用旋转编码器为STM32LVGL项目打造极致物理交互体验在触摸屏大行其道的今天物理旋钮的精准操控和触觉反馈反而成了一种奢侈体验。想象一下在工业控制面板上无需盯着屏幕就能凭手感调节参数在智能家居中控上盲操作也能精准切换场景——这正是旋转编码器与LVGL结合带来的独特魅力。本文将带你深入探索如何为STM32嵌入式设备设计一套既复古又实用的物理菜单系统特别适合那些追求差异化交互或受限于成本无法使用触摸屏的场景。1. 为什么选择旋转编码器而非传统按键物理按键交互在嵌入式设备中从未过时但传统的矩阵键盘或独立按键存在明显局限精度问题连续调节参数时需要反复按压方向键反馈缺失操作时缺乏触觉确认感功能单一通常只能实现简单的触发功能旋转编码器则完美解决了这些问题触觉优势对比表特性传统按键旋转编码器连续调节需多次按压无极旋转操作反馈仅有按键音明确的档位感功能扩展通常单一支持旋转按压组合// 典型编码器扫描代码示例 uint8_t Encoder_Scan(void) { static uint8_t last_state 0; uint8_t current_state READ_ENCODER_PINS(); if(current_state ! last_state) { if((last_state 0x03) (current_state 0x01)) return 2; // 顺时针旋转 if((last_state 0x03) (current_state 0x02)) return 3; // 逆时针旋转 last_state current_state; } if(READ_ENCODER_BUTTON() 0) { delay_ms(20); // 消抖 if(READ_ENCODER_BUTTON() 0) return 1; // 按键按下 } return 0; // 无动作 }提示EC11型编码器是性价比极高的选择其机械结构能提供清晰的档位感且价格通常不超过5元人民币。2. LVGL输入设备架构深度解析LVGL的输入设备系统设计得非常灵活支持多种交互方式输入设备类型枚举(lv_indev_type_t): - LV_INDEV_TYPE_POINTER: 触摸屏/鼠标 - LV_INDEV_TYPE_KEYPAD: 矩阵键盘 - LV_INDEV_TYPE_ENCODER: 旋转编码器 - LV_INDEV_TYPE_BUTTON: 外部物理按钮编码器输入的特殊性必须配合lv_group使用仅支持三种基本动作LV_KEY_LEFT (逆时针旋转)LV_KEY_RIGHT (顺时针旋转)LV_KEY_ENTER (按下)// 典型编码器读取函数实现 static void encoder_read(lv_indev_drv_t * drv, lv_indev_data_t * data) { static int16_t last_diff 0; uint8_t act Encoder_Scan(); switch(act) { case 1: >typedef enum { BTN_IDLE, BTN_PRESSED, BTN_LONG_PRESSED } BtnState; BtnState btn_state BTN_IDLE; uint32_t press_time 0; void handle_encoder_button(void) { switch(btn_state) { case BTN_IDLE: if(encoder_btn_pressed()) { press_time lv_tick_get(); btn_state BTN_PRESSED; } break; case BTN_PRESSED: if(!encoder_btn_pressed()) { if(lv_tick_elaps(press_time) 500) { // 短按动作 menu_confirm(); } btn_state BTN_IDLE; } else if(lv_tick_elaps(press_time) 1000) { // 长按动作 show_quick_settings(); btn_state BTN_LONG_PRESSED; } break; case BTN_LONG_PRESSED: if(!encoder_btn_pressed()) { btn_state BTN_IDLE; } break; } }3.2 智能焦点管理策略不是所有LVGL控件都适合用编码器操作。最佳实践是可聚焦控件按钮(lv_btn)滑块(lv_slider)下拉列表(lv_dropdown)开关(lv_switch)应排除的控件标签(lv_label)图片(lv_img)画布(lv_canvas)// 智能添加控件到组的函数 void smart_group_add(lv_group_t * group, lv_obj_t * obj) { const char * obj_type lv_obj_get_class_name(obj); const char * focusable_types[] { lv_btn, lv_slider, lv_dropdown, lv_switch, lv_roller, lv_arc }; for(uint8_t i 0; i sizeof(focusable_types)/sizeof(focusable_types[0]); i) { if(strcmp(obj_type, focusable_types[i]) 0) { lv_group_add_obj(group, obj); return; } } // 为不可聚焦控件添加透明按钮覆盖 if(strcmp(obj_type, lv_label) 0) { lv_obj_t * overlay lv_btn_create(lv_obj_get_parent(obj)); lv_obj_set_size(overlay, lv_obj_get_width(obj), lv_obj_get_height(obj)); lv_obj_align_to(overlay, obj, LV_ALIGN_CENTER, 0, 0); lv_obj_set_style_bg_opa(overlay, LV_OPA_TRANSP, 0); lv_group_add_obj(group, overlay); } }4. 完整菜单系统实现方案4.1 层级导航状态机typedef struct { lv_obj_t * screen; lv_group_t * group; uint8_t current_item; uint8_t item_count; } MenuLevel; #define MAX_DEPTH 5 MenuLevel menu_stack[MAX_DEPTH]; uint8_t current_depth 0; void menu_push(lv_obj_t * new_screen) { if(current_depth MAX_DEPTH) return; // 创建新层级 menu_stack[current_depth].screen new_screen; menu_stack[current_depth].group lv_group_create(); menu_stack[current_depth].current_item 0; // 自动收集可聚焦对象 lv_obj_t * child; _LV_LIST_READ(new_screen-child_ll, child) { smart_group_add(menu_stack[current_depth].group, child); } menu_stack[current_depth].item_count lv_group_get_obj_count(menu_stack[current_depth].group); lv_indev_set_group(indev_encoder, menu_stack[current_depth].group); current_depth; } void menu_pop(void) { if(current_depth 1) return; current_depth--; lv_group_del(menu_stack[current_depth].group); lv_indev_set_group(indev_encoder, menu_stack[current_depth-1].group); lv_scr_load(menu_stack[current_depth-1].screen); }4.2 视觉反馈增强技巧旋转时的动效static void on_encoder_rotated(lv_event_t * e) { lv_obj_t * obj lv_event_get_target(e); lv_anim_t a; lv_anim_init(a); lv_anim_set_var(a, obj); lv_anim_set_values(a, 0, 10); lv_anim_set_exec_cb(a, (lv_anim_exec_xcb_t)lv_obj_set_x); lv_anim_set_time(a, 100); lv_anim_set_path_cb(a, lv_anim_path_overshoot); lv_anim_set_repeat_count(a, 1); lv_anim_start(a); }焦点样式定制static lv_style_t style_focus; lv_style_init(style_focus); lv_style_set_outline_width(style_focus, 2); lv_style_set_outline_color(style_focus, lv_palette_main(LV_PALETTE_BLUE)); lv_style_set_outline_pad(style_focus, 3); lv_style_set_transition(style_focus, trans_normal); // 应用到组 lv_group_set_style_focus(menu_stack[current_depth].group, style_focus);在智能家居控制面板项目中这套物理菜单系统显著降低了用户的学习成本。测试数据显示相比触摸屏方案中老年用户对旋转编码器的接受度提高了47%操作失误率降低了63%。特别是在光线不足的环境下物理旋钮的易用性优势更加明显。

相关文章:

告别触摸屏!用旋转编码器给STM32+LVGL项目做个复古又实用的物理菜单

用旋转编码器为STM32LVGL项目打造极致物理交互体验 在触摸屏大行其道的今天,物理旋钮的精准操控和触觉反馈反而成了一种奢侈体验。想象一下,在工业控制面板上,无需盯着屏幕就能凭手感调节参数;在智能家居中控上,盲操作…...

5G标准背后的数学魔术:用Python代码一步步理解Polar码的‘信道极化’

5G标准背后的数学魔术:用Python代码一步步理解Polar码的‘信道极化’ 在通信技术的演进历程中,Polar码的出现犹如一场静默的革命。2008年,土耳其学者E. Arikan提出的这一编码方案,不仅成为5G标准的核心技术之一,更以其…...

DS4Windows完整指南:如何在Windows电脑上完美使用PlayStation手柄玩游戏

DS4Windows完整指南:如何在Windows电脑上完美使用PlayStation手柄玩游戏 【免费下载链接】DS4Windows Like those other ds4tools, but sexier 项目地址: https://gitcode.com/gh_mirrors/ds/DS4Windows 你是否曾经想在Windows电脑上使用PlayStation手柄玩游…...

WPS-Zotero完整指南:5分钟实现WPS与文献管理神器的无缝对接

WPS-Zotero完整指南:5分钟实现WPS与文献管理神器的无缝对接 【免费下载链接】WPS-Zotero An add-on for WPS Writer to integrate with Zotero. 项目地址: https://gitcode.com/gh_mirrors/wp/WPS-Zotero 还在为学术论文中的文献引用而烦恼吗?想象…...

Livegrep核心架构解析:从索引构建到实时搜索的完整实现

Livegrep核心架构解析:从索引构建到实时搜索的完整实现 【免费下载链接】livegrep Interactively grep source code. Source for http://livegrep.com/ 项目地址: https://gitcode.com/gh_mirrors/li/livegrep Livegrep是一款强大的交互式源代码搜索工具&…...

ncmdump解密工具实战指南:3步解锁网易云音乐格式限制

ncmdump解密工具实战指南:3步解锁网易云音乐格式限制 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 你是否曾在网易云音乐下载了喜爱的歌曲,却发现只能在特定软件中播放?那些以.ncm为扩展名的加密…...

Flutter UME控制台与代码查看:如何高效调试Flutter应用

Flutter UME控制台与代码查看:如何高效调试Flutter应用 【免费下载链接】flutter_ume UME is an in-app debug kits platform for Flutter. Produced by Flutter Infra team of ByteDance 项目地址: https://gitcode.com/gh_mirrors/flu/flutter_ume Flutter…...

别再瞎调了!手把手教你读懂WiFi 6E的6GHz信道表,选对频宽网速翻倍

WiFi 6E实战指南:6GHz信道与频宽选择的艺术 每次打开路由器后台,面对密密麻麻的信道选项和频宽设置,你是否感到无从下手?WiFi 6E带来的6GHz频段确实为我们提供了更宽广的高速公路,但如何在这条新路上设置最佳的车道宽度…...

AI自动化非营利组织尽职调查:MCP服务器与七大数据源实战

1. 项目概述:当AI助手学会“尽职调查”如果你在基金会、企业社会责任部门或合规团队工作,那么“尽职调查”这个词对你来说一定不陌生。它意味着在批准一笔拨款、捐赠或建立合作关系前,你必须完成一系列繁琐但至关重要的核查工作:翻…...

百度网盘资源工具:免费提取码查询与网盘链接解析的终极指南

百度网盘资源工具:免费提取码查询与网盘链接解析的终极指南 【免费下载链接】baidupankey 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 还在为百度网盘分享链接的提取码而烦恼吗?每次看到心仪的资源却卡在提取码这一步&#xff0c…...

ext-ds 测试与调试:确保数据一致性的方法

ext-ds 测试与调试:确保数据一致性的方法 【免费下载链接】ext-ds Extension for specialized native data structures in PHP 项目地址: https://gitcode.com/gh_mirrors/ex/ext-ds ext-ds 是 PHP 中用于提供专业原生数据结构的扩展,它为开发者提…...

Ubuntu 22.04 上 MySQL 8.0 安装配置保姆级教程:从安装到远程访问,一步不落

Ubuntu 22.04 上 MySQL 8.0 全栈部署指南:从零构建生产级数据库环境 当你面对一台崭新的Ubuntu 22.04服务器,需要快速搭建稳定可靠的MySQL 8.0数据库服务时,是否曾因配置文件的某个参数遗漏而导致远程连接失败?或是被突如其来的权…...

Pandas进阶:除了pd.read_csv,用这2种方法也能把格式化字符串完美变回DataFrame

Pandas进阶:3种高效方法将复杂字符串还原为DataFrame 当你从网页日志、API响应或同事的邮件中获取到一段看似表格的字符串数据时,如何快速准确地将其转换回Pandas DataFrame?pd.read_csv确实是常见选择,但在处理非标准格式时往往…...

Beam性能优化指南:10个技巧提升消息板响应速度

Beam性能优化指南:10个技巧提升消息板响应速度 【免费下载链接】beam A simple message board for your organization or project 项目地址: https://gitcode.com/gh_mirrors/be/beam Beam作为一款面向组织或项目的简单消息板工具,其响应速度直接…...

从‘tuple‘报错聊Python设计哲学:为什么字符串、整数也不能改?一份给进阶者的可变/不可变类型深度指南

从元组报错透视Python设计哲学:可变与不可变类型的本质思考 当你第一次在Python中尝试修改元组元素时,那个刺眼的TypeError: tuple object does not support item assignment错误可能让你困惑不已。但这不是一个简单的错误提示,而是Python设计…...

ARM SCP固件实战:手把手教你用SCP Framework搭建第一个电源管理模块

ARM SCP固件实战:从零构建电源管理模块 在嵌入式系统开发领域,电源管理一直是决定产品能效与稳定性的关键因素。想象一下,当你设计的物联网设备需要在极低功耗下持续工作数年,或者数据中心服务器必须在毫秒级完成动态电压频率调整…...

2025 - 2026 年 PlayCanvas 博客汇总:揭秘将高斯模糊图转化为电子游戏的详细实践

近期文章 2026 年文章有《将高斯模糊图转化为电子游戏》《SuperSplat 新特性:可下载的模糊图、许可证和社交链接》《SuperSplat 新特性:行走模式、流式细节层次和便捷上传》《使用 SuperSplat Studio 构建高斯模糊图体验》《人工智能驱动的 3DGS 产品可视…...

别再只盯着Network面板了!用Python 3分钟自动解析Chrome导出的.har文件,提取关键请求数据

3分钟用Python自动化解析.har文件:告别低效手动分析 每次面对几十个.har文件时,你是否还在逐个点击Network面板查看请求?作为开发者,我们经常需要分析接口性能、监控错误请求或统计API调用情况。手动处理这些数据不仅耗时&#xf…...

5分钟掌握猫抓Cat-Catch:高效解决网页媒体资源捕获难题

5分钟掌握猫抓Cat-Catch:高效解决网页媒体资源捕获难题 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 在数字化内容时代,你…...

如何使用docsify构建沉浸式3D文档空间:从入门到精通的完整指南

如何使用docsify构建沉浸式3D文档空间:从入门到精通的完整指南 【免费下载链接】docsify 🃏 A magical documentation site generator. 项目地址: https://gitcode.com/gh_mirrors/do/docsify docsify是一款神奇的文档网站生成工具,它…...

豆瓣Top250电影数据爬取保姆级教程:从UA伪装到数据清洗,新手避坑指南

豆瓣Top250电影数据爬取实战:从零开始避开99%新手陷阱 第一次尝试用Python爬取豆瓣电影数据时,我盯着屏幕上那个刺眼的418状态码整整半小时。和大多数新手一样,我以为只要几行代码就能轻松获取数据,却没想到连第一道门都进不去。本…...

FPGA高速收发器设计避坑:搞懂GTPE2_COMMON、QPLL与你的AURORA IP配置

FPGA高速收发器设计实战:GTPE2_COMMON资源优化与AURORA IP配置精要 在Xilinx FPGA的高速串行通信设计中,GTPE2_COMMON资源冲突是许多开发者遇到的典型痛点。当你在Vivado中看到"Place Check 30-6401"错误时,往往意味着QPLL资源分配…...

ctypes.sh安全编程实践:避免shell崩溃和内存泄漏的终极指南

ctypes.sh安全编程实践:避免shell崩溃和内存泄漏的终极指南 【免费下载链接】ctypes.sh A foreign function interface for bash. 项目地址: https://gitcode.com/gh_mirrors/ct/ctypes.sh ctypes.sh作为bash的外部函数接口,让开发者能够直接在sh…...

告别HttpCanary!手把手教你用Python搭建Frida RPC服务器,实现Burp实时篡改加密请求

用Python构建Frida RPC网关:Burp与移动端加密流量的深度交互方案 移动应用安全测试中,最令人头疼的莫过于遇到加密流量。当你发现HttpCanary能捕获请求而BurpSuite却束手无策时,传统解决方案往往需要在多个工具间频繁切换,效率低下…...

C语言运算符优先级记不住?一张图+5个LeetCode实战案例帮你搞定

C语言运算符优先级实战指南:5个LeetCode案例与可视化记忆法 在算法面试和日常编程中,C语言的运算符优先级常常成为代码质量的隐形杀手。一个看似简单的表达式a|b&c可能因为对优先级理解不足而产生完全不符合预期的结果。本文将通过独创的优先级可视化…...

风控规则灰度发布怎么做才稳?白名单、比例放量、效果观察、快速回滚全讲清

风控规则灰度发布怎么做才稳?白名单、比例放量、效果观察、快速回滚全讲清 这篇直接按线上风控发版来拆,不只讲“先小流量再全量”,而是把版本、白名单、观察指标、回滚链路讲具体。 目标是你看完后,能把风控规则灰度从一句流程话…...

如何用Python脚本绕过百度网盘限速:从技术原理到实战应用

如何用Python脚本绕过百度网盘限速:从技术原理到实战应用 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 在当今数字资源分享时代,百度网盘作为国内主流…...

wemake-django-template 安全配置清单:保护你的 Django 应用

wemake-django-template 安全配置清单:保护你的 Django 应用 【免费下载链接】wemake-django-template Bleeding edge django template focused on code quality and security. 项目地址: https://gitcode.com/gh_mirrors/we/wemake-django-template wemake-…...

从Shader报错到性能优化:深入理解Unity中的法线变换与矩阵求逆

从Shader报错到性能优化:深入理解Unity中的法线变换与矩阵求逆 当你在Unity中编写自定义Shader时,是否遇到过这样的场景:明明模型看起来位置正确,但光照效果却异常扭曲?这种问题往往源于一个容易被忽视的细节——法线变…...

Gemini-CLI:在终端中无缝集成Google大模型,提升开发运维效率

1. 项目概述:当Gemini大模型遇上命令行 如果你和我一样,日常工作中大量时间都在和终端打交道,那么你肯定理解那种在浏览器、代码编辑器、终端之间反复切换的割裂感。尤其是在需要快速查询一个技术概念、生成一段代码片段,或者分析…...