公共 UI 与 LED 显示
本页介绍 AD23N 固件 SDK 中「公共 UI 与 LED 显示」子系统:以 LED 5×7 点阵屏为输出载体、以菜单(Menu)状态机为核心的公共用户界面框架,覆盖从应用层 UI_menu() 调用到 LED 扫描驱动的完整链路。
Purpose and Scope
本页面向需要理解或扩展 AD23N 上 LED 显示逻辑的嵌入式工程师,内容覆盖:
sdk/app/src/mbox_flash/common/ui/目录下的 UI API 层(ui_api.h/c)与 LED 驱动层(led5x7_driver.h/c)以及公共工具层(ui_common.h/c)。- 菜单(Menu)枚举、
UI_VAR显示变量、菜单自动返回与定时刷新机制。 - LED 显示缓存结构、状态图标位(
LED_STATUS)、亮度/闪烁控制与 IO 端口映射。 - 配置开关(
UI_ENABLE、KEY_IR_EN、USB_DEVICE_EN等)对编译行为的影响。
不属于本页范围(由其他目录页覆盖):具体的音乐播放逻辑(music_play.h)、文件系统扫描(play_file.h)、消息/按键事件分发(msg.h)、以及各业务模块(USB PC、FM、RTC、闹钟)本身的实现。本页只描述它们如何通过 UI_menu() 与 LED 显示子系统交互。
概述
在 AD23N 的 mbox_flash(音箱类)应用中,LED 5×7 点阵屏是主要的用户信息输出设备。系统没有图形化 UI,而是采用**「菜单 + 参数」模型**:任意业务模块(音乐播放、FM 收音、USB PC 模式、AUX、RTC 等)在需要改变显示内容时,只需调用统一的界面接口:
UI_menu(MENU_XXX, arg);
UI 层维护一个全局的 UI_VAR UI_var 结构,记录当前菜单、主菜单、返回计数器和当前参数;UI_menu_api() 根据菜单类型决定是切换显示还是仅在主界面刷新,随后分发到 LED5X7_show_*() 系列函数,将业务数据渲染成 5×7 点阵缓存(bShowBuff)。驱动层则通过定时扫描把缓存搬运到 GPIO 端口,完成动态扫描显示。
这种分层设计的目的:
- 解耦业务与显示:业务模块不关心点阵如何扫描,只发菜单事件;
- 集中管理显示状态:菜单自动返回、超时、主界面刷新等策略集中在
UI_menu_api()一处实现; - 低成本复用:
LED5X7_show_*函数族覆盖音乐、FM、音量、EQ、时钟等全部显示场景,新增显示只需增加一个菜单枚举和一个 show 函数。
架构
flowchart TD
subgraph sg_App["应用层 (mbox_flash)"]
Music["音乐播放模块"] -->|"UI_menu(MENU_MUSIC_MAIN, arg)"| UIAPI
FM["FM 收音模块"] -->|"UI_menu(MENU_FM_MAIN, arg)"| UIAPI
PC["USB PC 模块"] -->|"UI_menu(MENU_PC_MAIN, arg)"| UIAPI
IR["红外按键/消息"] -->|"UI_menu / post_msg"| UIAPI
end
subgraph sg_UI["UI 层 (common/ui)"]
UIAPI["UI_menu_api()<br/>UI_VAR 状态机"]
UIAPI -->|"分发 switch(bCurMenu)"| SHOW["LED5X7_show_*() 系列"]
end
subgraph sg_LED["LED 驱动层"]
SHOW --> VAR["LED5X7_VAR<br/>bShowBuff / bBrightness"]
SCAN["LED5X7_scan()<br/>定时扫描"]
VAR --> SCAN
SCAN -->|"动态扫描 GPIO"| HW
end
subgraph sg_HW["硬件层"]
HW["LED 5x7 点阵屏<br/>LED_PORT0 ~ PORT6"]
end
subgraph sg_Common["公共工具"]
UIAPI -.->|"字模/公共函数"| COMMON["ui_common.c/h"]
end
架构说明:
- 应用层是显示内容的"生产者":音乐、FM、PC、红外按键等模块通过
UI_menu(menu, arg)请求显示,或通过post_msg()注入定时/超时消息(如MSG_INPUT_TIMEOUT)。 - UI 层是显示状态的"裁决者":
UI_menu_api()内部维护bCurMenu/bMainMenu/bMenuReturnCnt/bCurArg,处理菜单切换、自动返回和刷新去重;随后按bCurMenu分发到具体渲染函数。 - LED 驱动层是渲染与扫描的"执行者":
LED5X7_show_*()把业务参数转换成字模写入bShowBuff,LED5X7_scan()定时将缓存输出到 7 个端口位(LED_PORT0~LED_PORT6),实现动态扫描。 - 公共工具层
ui_common提供字模表和跨模块的公共渲染辅助函数,被 show 函数族复用。
UI 层所有代码通过段选择指令(#pragma code_seg(".led_ui.text") 等)放入独立的 .led_ui.* 段,便于链接期控制内存/代码布局(见 ui_api.c)。
核心控制流:从菜单事件到点阵刷新
sequenceDiagram
participant Biz as 业务模块 (音乐/FM/PC/IR)
participant UI as UI_menu_api() (ui_api.c)
participant VAR as UI_VAR / LED5X7_VAR
participant DRV as LED5X7_show_*()
participant SCAN as LED5X7_scan() (定时器)
participant HW as LED 端口 (PORT0~6)
Biz->>UI: UI_menu(MENU_XXX, arg)
activate UI
UI->>UI: 处理 MENU_MAIN 自动返回 / 0x80 刷新判定
UI->>VAR: 更新 bCurMenu / bCurArg / bMenuReturnCnt
UI->>DRV: switch(bCurMenu) 分发
deactivate UI
DRV->>VAR: 写 bShowBuff[0..4] + bBrightness
loop 每个扫描周期 (定时器中断/任务)
SCAN->>VAR: 读取 bShowBuff / 闪烁标志
SCAN->>HW: 输出位码到 LED_PORT0~6
HW-->>SCAN: 硬件点亮对应 LED 点
end
UI_menu_api() 决策逻辑
UI_menu_api(u8 menu, int arg) 是整个 UI 层的入口,定义于 ui_api.c。其决策过程分三档:
1. menu == MENU_MAIN(0xFF)—— 自动返回主界面
- 若
bMenuReturnCnt < UI_RETURN(UI_RETURN定义为 3,即 3×500ms = 1.5 秒),则累加计数器,并在计数到达 3 时执行真正的返回:先LED5X7_clear_icon()清图标,再切回bMainMenu。 - 在
KEY_IR_EN使能时,若当前是MENU_INPUT_NUMBER(数字输入),则不直接返回,而是post_msg(1, MSG_INPUT_TIMEOUT)投递输入超时消息,把"超时"作为业务事件交给消息循环处理——这是显示层与事件层解耦的典型做法。 - 计数未满时保持
ui_arg = UI_var.bCurArg(沿用原参数),避免刷新主界面时参数丢失。 - 计数器已满(≥3)后,若当前已回到主界面则直接返回(不重复刷新);否则切回
bMainMenu。
2. menu > 0x80 —— 定时刷新类菜单
这类菜单(MENU_200MS_REFRESH、MENU_100MS_REFRESH、MENU_HALF_SEC_REFRESH 等)表示"仅刷新,不切换界面"。代码要求当前菜单必须是主界面才执行刷新,否则直接忽略。这保证定时器驱动的周期性刷新不会打断用户正在浏览的二级界面(如音量、EQ)。
3. menu <= 0x80 且非 MENU_MAIN —— 普通界面切换
- 先
LED5X7_clear_icon()清除全部状态图标,避免旧图标残留; - 若目标菜单不是主菜单,则把
bMenuReturnCnt清零,重新启动自动返回倒计时(等待UI_RETURN个周期后回主界面); - 更新
bCurMenu = menu、bCurArg = ui_arg。
无论哪条路径,最后都会 LED5X7_setX(0) 复位显示坐标,然后进入 switch (UI_var.bCurMenu) 分发(ui_api.c L85-L120):
| 分发组 | 菜单 | 渲染函数 |
|---|---|---|
| 系统/开机/等待 | MENU_POWER_UP、MENU_IDLE、MENU_WAIT、MENU_PC_MAIN、MENU_PC_VOL_UP、MENU_PC_VOL_DOWN、MENU_AUX_MAIN | LED5X7_show_string_menu() |
| 公共信息 | MENU_MAIN_VOL | LED5X7_show_volume() |
| 音乐相关 | MENU_MUSIC_MAIN、MENU_PAUSE | LED5X7_show_music_main() |
| 音乐相关 | MENU_FILENUM | LED5X7_show_filenumber() |
| 音效 | MENU_HW_EQ(条件编译)、MENU_DEC_EQ | LED5X7_show_hw_eq() / LED5X7_show_dec_eq() |
| 数字输入 | MENU_INPUT_NUMBER(KEY_IR_EN) | LED5X7_show_IR_number() |
菜单枚举与分层语义
菜单枚举定义于 ui_api.h,其数值区间本身就是一种设计约定:
0x00 ~ 0x7F:普通界面(可切换、带自动返回),如MENU_POWER_UP=0、MENU_IDLE、MENU_PLAY、MENU_FM_MAIN等;0x80 ~ 0xFE:刷新/设置类菜单(仅在主界面生效),如MENU_200MS_REFRESH=0x80、MENU_100MS_REFRESH、MENU_SET_EQ、MENU_SET_PLAY_MODE、MENU_HALF_SEC_REFRESH、MENU_POWER_DOWN;0xFF:MENU_MAIN,特殊值,表示"回到主界面"。
UI_VAR 结构(ui_api.h L47-L52)集中保存显示状态:
typedef struct _UI_VAR {
u8 bCurMenu; //< 当前菜单
u8 bMainMenu; //< 主菜单(自动返回目标)
u8 bMenuReturnCnt; //< 菜单返回计数器
int bCurArg; //< 当前菜单参数
} UI_VAR;
bMainMenu 由业务模块通过 SET_UI_MAIN(x) 宏设置,决定"返回主界面"最终回到哪里——典型如音乐播放时主菜单为 MENU_MUSIC_MAIN,FM 模式下为 MENU_FM_MAIN。
对外宏封装与编译裁剪
ui_api.h L59-L68 提供宏封装,使业务代码无需关心底层实现:
#if UI_ENABLE
extern UI_VAR UI_var; /*UI 显示变量*/
#define UI_init() UI_init_api()
#define UI_menu(x, y) UI_menu_api(x, y)
#define SET_UI_MAIN(x) UI_var.bMainMenu = x
#else
#define UI_init(...)
#define UI_menu(...)
#define SET_UI_MAIN(...)
#endif
当 UI_ENABLE 未定义/为 0 时,所有 UI 调用被编译为空操作——这是产品级裁剪开关:无 LED 屏的低配机型可整体关闭显示功能,同时业务代码无需改动。UI_init() 用于初始化 UI_var 与 LED 驱动,UI_menu(x,y) 为全局显示入口。
LED 驱动层:显示缓存、状态位与端口映射
LED5X7_VAR 显示变量
驱动层的核心状态定义在 led5x7_driver.h L7-L14:
typedef struct _LED5X7_VAR {
u8 bCoordinateX; //<X 坐标
u8 bFlashChar; //<字符位闪烁
u8 bFlashIcon; //<图标闪烁
u8 bShowBuff[5]; //<显示缓存
u8 bBrightness; //<亮度控制
u8 bShowBuff1[8];
} LED5X7_VAR;
设计要点:
bShowBuff[5]是主显示缓存,最多容纳 5 个字符的 5×7 点阵数据;bShowBuff1[8]为辅助缓存(如滚动/扩展内容)。两个缓存 +bCoordinateX(当前 X 坐标)支持字符串/菜单的逐段渲染。bFlashChar与bFlashIcon分别是字符位闪烁与图标闪烁控制位,扫描时据此交替亮灭,实现"正在等待/输入中"等提示效果(如LED5X7_show_waiting())。bBrightness提供亮度控制,配合set_LED_fade_out()(渐灭)与set_LED_all_on()(全亮)实现电源开关的柔和过渡动画。
LED_STATUS 宏把缓存最后一个字节作为图标状态寄存器:
#define LED_STATUS LED5X7_var.bShowBuff[4]
#define LED_A BIT(0) ... #define LED_H BIT(7)
//for LED_STATUS —— 每个状态图标占用一个位
#define LED_PLAY LED_A // 播放图标
#define LED_PAUSE LED_B // 暂停图标
#define LED_USB LED_C // USB 图标
#define LED_SD LED_D // SD 卡图标
#define LED_2POINT LED_E // 冒号(时间分隔点)
#define LED_MHZ LED_F // MHz 单位
#define LED_MP3 LED_G // MP3 图标
#define LED_FM LED_H // FM 图标
见 led5x7_driver.h L48-L67。这种位图式图标寄存器使多个状态(如"播放+USB")可以同时点亮,且业务层只需 LED_STATUS |= LED_PLAY 这类位操作即可控制图标,无需关心点阵细节。
端口映射与硬件适配
led5x7_driver.h L69-L90 用条件编译给出两套端口定义:
#if 1
#define LED_PORT0 BIT(12) // 行扫描线映射到 32 位 IO 掩码
#define LED_PORT1 BIT(11)
#define LED_PORT2 BIT(10)
#define LED_PORT3 BIT(9)
#define LED_PORT4 BIT(7)
#define LED_PORT5 BIT(6)
#define LED_PORT6 BIT(4)
#define LED_PORT_ALL (LED_PORT0 | LED_PORT1 | LED_PORT2 | LED_PORT3 | LED_PORT4 | LED_PORT5 | LED_PORT6)
#else
#define LED_PORT0 IO_PORTA_04 // 备选方案:直接映射到 GPIO 宏
...
#endif
第一套(默认启用)用 BIT(n) 位掩码描述端口,便于通过一次 32 位端口写操作同时控制 7 根扫描线;第二套映射到 IO_PORTA_xx 具体引脚宏。切换方案只需改动条件编译开关,硬件改版时驱动层零改动。LED5X7_scan() 按行/列分时驱动(动态扫描),利用人眼视觉暂留降低 IO 占用与功耗;实际扫描时序与字模表实现在 led5x7_driver.c 中(该文件同时包含 LED5X7_show_* 渲染函数族与 LED5X7_init)。
渲染函数族总览
| 函数 | 用途 |
|---|---|
LED5X7_setX(u8 X) | 设置当前 X 坐标 |
LED5X7_show_string_menu(u8 menu) | 按菜单显示固定字符串(开机/PC/AUX 等) |
LED5X7_show_char / show_number | 显示单字符/数字 |
LED5X7_show_music_main(int arg) / show_filenumber(int arg) | 音乐播放主界面、文件序号 |
LED5X7_show_volume() / show_dec_eq(u32 arg) / show_hw_eq() | 音量条、软件/硬件 EQ |
LED5X7_show_playmode(int arg) / show_fm_main() / show_fm_station() | 播放模式、FM 频率/电台 |
LED5X7_show_alarm() / show_RTC_main() / show_pc_main() 等 | 闹钟、时钟、PC 模式 |
LED5X7_show_pause() / show_waiting() / show_IR_number() | 暂停、等待动画、红外数字输入 |
LED5X7_clear_icon() | 清空图标位 |
set_LED_fade_out() / set_LED_all_on() | 渐灭 / 全亮(电源过渡) |
函数声明集中在 led5x7_driver.h L17-L44。LED5X7_scan() 与 LED5X7_init() 是驱动入口,分别被定时器/主循环与系统初始化调用。
使用示例
1. 业务模块请求显示(以音乐播放为例)
业务侧的标准用法是直接调用宏,把菜单与参数交给 UI 层:
UI_menu(MENU_MUSIC_MAIN, cur_play_time);
对应 ui_api.h 中的宏定义:#define UI_menu(x, y) UI_menu_api(x, y),业务代码无需 #if 判断,裁剪由宏在编译期完成。参见 ui_api.h L59-L68。
2. UI 层分发到渲染函数(真实代码)
UI_menu_api() 根据当前菜单将参数转发给 LED 渲染函数:
void UI_menu_api(u8 menu, int arg)
{
int ui_arg = arg;
/*界面属性-非主界面自动返回*/
if (menu == MENU_MAIN) {
if (UI_var.bMenuReturnCnt < UI_RETURN) {
UI_var.bMenuReturnCnt++;
if (UI_var.bMenuReturnCnt == UI_RETURN) {
LED5X7_clear_icon();
#if KEY_IR_EN
if (UI_var.bCurMenu == MENU_INPUT_NUMBER) {
post_msg(1, MSG_INPUT_TIMEOUT); //输入超时
} else
#endif
{
UI_var.bCurMenu = UI_var.bMainMenu;
UI_var.bCurArg = ui_arg;
}
} else {
ui_arg = UI_var.bCurArg;
}
}
...
}
...
switch (UI_var.bCurMenu) {
/*-----Common Info UI*/
case MENU_MAIN_VOL:
LED5X7_show_volume();
break;
/*-----Music Related UI*/
case MENU_MUSIC_MAIN:
case MENU_PAUSE:
LED5X7_show_music_main(ui_arg);
break;
case MENU_FILENUM:
LED5X7_show_filenumber(ui_arg);
break;
...
}
来源:ui_api.c L36-L109。注意 MENU_MUSIC_MAIN 与 MENU_PAUSE 共用同一渲染函数、仅参数不同——这体现了"显示语义归菜单、渲染细节归驱动"的分层。
3. 设置主菜单(自动返回目标)
SET_UI_MAIN(MENU_MUSIC_MAIN);
宏展开为 UI_var.bMainMenu = MENU_MUSIC_MAIN,此后用户在音量/EQ 等二级界面停留超过 UI_RETURN(3×500ms)会自动回到音乐主界面。见 ui_api.h L63。
4. 图标位控制(驱动层)
LED_STATUS |= LED_PLAY; // 点亮播放图标
LED_STATUS &= ~LED_SD; // 熄灭 SD 图标
通过 LED_STATUS(即 bShowBuff[4])的位操作即可组合任意状态图标,扫描时由驱动一并输出。定义见 led5x7_driver.h L48-L67。
配置选项
| 配置项 | 类型 | 默认/典型值 | 说明 |
|---|---|---|---|
UI_ENABLE | 宏开关 | 定义则启用 | 整体裁剪 UI:为 0 时 UI_init/UI_menu/SET_UI_MAIN 编译为空操作(ui_api.h L59-L68) |
KEY_IR_EN | 宏开关 | 依机型 | 使能红外按键:启用后 MENU_INPUT_NUMBER 有效,且输入超时改为投递 MSG_INPUT_TIMEOUT 消息(ui_api.c L45-L49) |
USB_DEVICE_EN | 宏开关 | 依机型 | 决定 MENU_PC_MAIN/MENU_PC_VOL_UP/MENU_PC_VOL_DOWN 菜单是否编译(ui_api.h L11-L15) |
AUDIO_HW_EQ_EN / PCM_SW_EQ_EN | 宏开关 | 依音频配置 | 任一使能时编译 MENU_HW_EQ 显示分支(ui_api.c L111-L115) |
UI_RETURN | 宏常量 | 3 | 自动返回延时计数(n×500ms),#define UI_RETURN 3(ui_api.h L54) |
LED_PORT0~6 / LED_PORT_ALL | 端口宏 | BIT(12)…BIT(4) | LED 扫描线 IO 掩码,备选方案映射 IO_PORTA_xx(led5x7_driver.h L69-L90) |
段选择 #pragma | 编译指令 | .led_ui.* | UI 层代码/数据放入独立段,便于 ROM/RAM 布局管理(ui_api.c L1-L5) |
API 参考
void UI_menu_api(u8 menu, int arg) — UI 显示界面处理函数
说明:全局显示入口。menu == MENU_MAIN 触发自动返回逻辑;menu > 0x80 表示仅刷新(须处于主界面);其余为界面切换。随后按 bCurMenu 分发到 LED5X7_show_*()。
参数:
menu(u8):目标菜单,取值见 ui_api.h L7-L45 的MENU_*枚举(普通界面 0x00~0x7F、刷新类 0x80~0xFE、MENU_MAIN=0xFF);arg(int):菜单参数,如播放时间、文件序号、音量值、EQ 档位等。
返回:无。副作用:更新 UI_var、清除图标、调用渲染函数。
注意:MENU_INPUT_NUMBER 超时路径在 KEY_IR_EN 下通过 post_msg(1, MSG_INPUT_TIMEOUT) 转交消息循环,不会在本函数内直接返回主界面(ui_api.c L46-L48)。
void UI_init_api(void) — UI 初始化
说明:初始化 UI_var 与 LED 驱动(LED5X7_init),由 UI_init() 宏在系统启动时调用。
void LED5X7_scan(void) — LED 动态扫描
说明:驱动层扫描入口,定时读取 LED5X7_VAR(显示缓存、闪烁标志、亮度)并输出到 LED_PORT0~6,实现动态扫描显示。应周期性调用(定时器中断或主循环轮询)。
void LED5X7_show_*(...) — 渲染函数族
说明:led5x7_driver.h 中声明的全部 LED5X7_show_* 函数(show_music_main、show_volume、show_dec_eq(u32 arg)、show_IR_number、show_playmode(int arg)、show_fm_main、show_alarm、show_RTC_main、show_waiting 等)均以业务参数(int/u32)为输入,将对应内容渲染进 bShowBuff/bShowBuff1 并设置图标位。完整列表见 led5x7_driver.h L17-L44。
void LED5X7_setX(u8 X) / LED5X7_clear_icon(void) / set_LED_fade_out(void) / set_LED_all_on(void)
LED5X7_setX:设置渲染起始 X 坐标;LED5X7_clear_icon:清零LED_STATUS(bShowBuff[4]),界面切换前调用以清除旧图标;set_LED_fade_out/set_LED_all_on:电源过渡效果(渐灭/全亮)。
故障模式、边界情况与并发
- 刷新丢失(时序竞争):
menu > 0x80的定时刷新仅在bCurMenu == bMainMenu时生效。若业务在二级界面(如 EQ 设置)期间发送MENU_200MS_REFRESH,该刷新被静默丢弃——这是有意的设计(避免打断用户浏览),但依赖方须接受"定时刷新可能不立即生效"。 - 自动返回与参数保留:
MENU_MAIN计数未满时强制ui_arg = UI_var.bCurArg,保证倒计时期间参数不被外部传入值覆盖;返回动作在计数等于UI_RETURN(3)的当次调用执行,之后计数保持 ≥3,避免重复返回。 - 红外输入超时:
MENU_INPUT_NUMBER场景下,MENU_MAIN不直接回主界面,而是post_msg(MSG_INPUT_TIMEOUT)。若消息循环未及时处理该消息,输入界面会短暂停留在超时状态——业务层应保证消息及时消费。 - 图标残留:普通界面切换前统一
LED5X7_clear_icon(),但刷新类(0x80 段)菜单不清图标,因此"主界面+图标"组合(如播放时显示 USB/SD 图标)可保持;若某刷新内容需隐藏图标,须由对应 show 函数自行处理。 - 并发模型:
UI_var与LED5X7_var均为全局单实例,典型调用上下文为单线程(主循环/消息循环)+定时扫描。若从 ISR 直接调用UI_menu/LED5X7_show_*,需要自行加临界区保护,源码未内置锁。 - 硬件差异:
#if 1与#else两套端口宏并存,若未按实际 PCB 匹配端口方案,扫描会显示错乱(花屏/暗屏)。改版时务必同步检查LED_PORT0~6映射。
性能与运维注意
- 扫描开销:
LED5X7_scan()每次输出 7 根线的位码,5 字符点阵 + 图标共 8×7 个点,单次扫描开销极小;主要成本在扫描频率(闪烁/亮度表现)与占用定时器节拍。若需降低功耗,可降低扫描频率或利用bBrightness做占空比调光。 - 代码/数据段布局:UI 层通过
#pragma强制放入.led_ui.text/.led_ui.data段。链接脚本若未正确保留这些段名,会出现链接错误或段溢出——新增 UI 文件时需保持相同的段声明。 - ROM 占用:
ui_common字模表(5×7 字符/图标)是静态常量,属可预估的固定开销;新增字符/图标主要增加.led_ui.text.const段体积。
扩展点
- 新增菜单:在
ui_api.h枚举中追加值(普通界面 0x00~0x7F 或刷新类 0x80~0xFE),并在ui_api.c的switch (UI_var.bCurMenu)中增加 case 分支分发到新的 show 函数。 - 新增渲染函数:在
led5x7_driver.h声明、led5x7_driver.c实现,写入bShowBuff并控制LED_STATUS图标位即可;字形复用ui_common字模。 - 新增状态图标:
LED_STATUS字节目前用到LED_A~LED_H(BIT(0)~BIT(7))共 8 位,已满;如需更多图标须扩展bShowBuff[4]之外的空间或增加缓存字节,并同步修改LED5X7_scan()的输出逻辑。 - 新的业务模块接入:无需改动驱动,只需在业务代码中调用
UI_menu(MENU_XXX, arg)并(必要时)SET_UI_MAIN()指定返回目标,即可获得自动返回、定时刷新等全部 UI 语义。 - 平台裁剪:通过
UI_ENABLE可整体关闭 UI;KEY_IR_EN/USB_DEVICE_EN/EQ 相关宏按产品特性裁剪菜单分支。
测试情况
源码目录未发现针对本子系统的独立单元测试文件(MCU 固件项目通常依赖整机验证)。建议的验证路径:开机自检(LED5X7_init 后全亮/渐灭)、各 MENU_* 切换与自动返回计时(3×500ms)、图标位组合显示(播放+USB/SD)、红外数字输入超时消息(MSG_INPUT_TIMEOUT)、定时刷新(200ms/100ms/500ms)在主/非主界面的行为差异。