一个适合MCU的分级菜单框架

框架结构体如下:

cpp 复制代码
struct ui_menu
{
    uint8_t item;                         // 当前选择的子菜单编号
    uint8_t level;                          // 菜单级别,0是最高级别,主菜单。
    struct ui_menu* parent;                 // 父菜单,即上一级菜单 
    struct ui_menu* items[UI_MENU_ITEM_MAX];//此菜单下的子菜单
    uint8_t (*on_Key_Up)(void);             // 返回值,是否是最后一个子项,可根据此返回值执行特定的操作
    uint8_t (*on_Key_Down)(void);           // 返回值,是否是最后一个子项,可根据此返回值执行特定的操作
    struct ui_menu* (*on_Key_Back)(void);   // 返回上一级菜单
    struct ui_menu* (*on_Key_OK)(uint8_t* flag);
    void (*menu_Show)(void);                // 显示逻辑在此处执行
    void (*menu_Enter)(uint8_t item);       // 进入此菜单会被调用一次
    void (*menu_Exit)(void);                // 退出此菜单会被调用一次
};

菜单的链接实现

cpp 复制代码
/*
 * 连接菜单
 * @param in:parent:父菜单,为空则为顶级菜单
 * @param in:item:父菜单下的一个菜单项,不能为空
 * @param in:itemIndex:本菜单功能不使用动态分配,索引不能超过最大索引。
 */
int UI_Menu_Link(ui_menu_t* parent,ui_menu_t* item,uint8_t itemIndex)
{
    if(item == NULL)
    {
        return -1;
    }
    if(itemIndex >= UI_MENU_ITEM_MAX)
    {
        return -1;
    }
    if(parent == NULL)
    {
        return -1;
    }
    item->level = parent->level + 1;        // 将当前项设置为父菜单的下一级
    item->parent = parent;
    parent->items[itemIndex] = item;
    return 0;
}

ui_menu_t* UI_Menu_Top_Get(ui_menu_t* item)
{
    ui_menu_t* top = item;
    if(top != NULL)
    {
        while(top->parent != NULL){
            top = top->parent;
        }
    }
    return top;

    
}

菜单的调用方式,根据不同的按键执行对应的功能。

cpp 复制代码
void UI_Page_Menu_Handler(uint16_t key)
{
    uint16_t keyEvent = key;
    uint8_t isSave = 0;     

    if(keyEvent == KEY_OK)      // 保存参数,进入下一步
    {
        if(curMenu->on_Key_OK)
        {
            curMenu = curMenu->on_Key_OK(&isSave);      // 调用当前菜单的OK
            if(curMenu->menu_Enter)
            {
                if(curMenu->level > lastMenu->level)
                {
                    curMenu->menu_Enter(lastMenu->itemID);
                }
            }
            lastMenu = curMenu;
        }
        else
        {
            isSave = 0xFF;
        }
        
        if(isSave == 1)      // 保存数据
        {

        }
        else if(isSave == 0)
        {

        }        
    }
    else if(keyEvent == KEY_BACK)
    {
        if(curMenu->menu_Exit)
        {
            curMenu->menu_Exit();
        }
        if(curMenu->on_Key_Back)
        {
            curMenu = curMenu->on_Key_Back();
            lastMenu = curMenu;
        }

    }
    else if(keyEvent == KEY_UP)
    {
        if(curMenu->on_Key_Up)
        {
            if(curMenu->on_Key_Up())
            {

            }
            else
            {

            }
        }        
    }
    else if(keyEvent == KEY_DOWN)
    {
        if(curMenu->on_Key_Down)
        {
            if(curMenu->on_Key_Down())
            {

            }
            else
            {

            }
        }
        
    }  
    curMenu->menu_Show();
}

本框架没有使用动态内存分配。在菜单分级较多的情况下,没有框架的支持,写起来会显得非常混乱。在框架的支持下,可以将各个菜单功能解耦合,利于后期的维护及扩展。

相关推荐
点灯小铭1 小时前
基于51单片机射频RFID卡考勤上课上班人数计数系统设计
单片机·嵌入式硬件·毕业设计·51单片机·课程设计
苏格拉真没有底2 小时前
MCU 软件断点注意事项!!!
单片机·嵌入式硬件
Shang131130487912 小时前
THCV215一种高速视频数据收发器,采用低电压差分信号(LVDS)技术支持高速串行数据传输,支持1080p/60Hz高分辨率传输
单片机·嵌入式硬件·高速视频收发器·thcv215·高速视频数据收发器
凯子坚持 c4 小时前
虚拟机一站式部署Claude Code &可视化UI界面
ui·编辑器·vim
No0d1es11 小时前
202506 电子学会青少年等级考试机器人五级器人理论真题
单片机·嵌入式硬件·青少年编程·机器人·电子学会·五级·理论综合
范纹杉想快点毕业14 小时前
C 语言主控开发与显控开发能力体系及技术栈详解,STM32、QT、嵌入式、边缘系统显示
stm32·单片机·tcp/ip·microsoft·fpga开发·51单片机·wpf
LJWWD16 小时前
AI小智单片机esps32-s3烧录教程
单片机·嵌入式硬件
嵌入式小李1 天前
stm32项目(25)——基于stm32的植物生长箱环境监测系统
stm32·单片机·嵌入式硬件
伽蓝_游戏1 天前
UGUI源码剖析(5):事件的旅程——EventSystem的架构与输入处理管线
游戏·ui·unity·架构·c#·游戏引擎·.net
小郝 小郝2 天前
开启单片机
c语言·单片机·嵌入式硬件·学习·51单片机