一个适合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();
}

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

相关推荐
失忆爆表症4 小时前
05_UI 组件库集成指南:Shadcn/ui + Tailwind CSS v4
前端·css·ui
不能跑的代码不是好代码5 小时前
STM32窗口看门狗(WWDG)知识点及标准库使用指南
stm32·单片机·嵌入式硬件
bingquan33335 小时前
在 Ghidra 中分析STM32裸机固件
stm32·单片机·嵌入式硬件
羽获飞5 小时前
从零开始学嵌入式之STM32——11.STM32---USART串行通讯
stm32·单片机·嵌入式硬件
宵时待雨7 小时前
STM32笔记归纳9:定时器
笔记·stm32·单片机·嵌入式硬件
逐步前行7 小时前
STM32_新建工程(寄存器版)
stm32·单片机·嵌入式硬件
bai5459367 小时前
STM32 CubeIDE 通过PWM占空比控制舵机角度
stm32·单片机·嵌入式硬件
北京迅为7 小时前
《【北京迅为】itop-3568开发板NPU使用手册》- 第 7章 使用RKNN-Toolkit-lite2
linux·人工智能·嵌入式·npu
松涛和鸣9 小时前
72、IMX6ULL驱动实战:设备树(DTS/DTB)+ GPIO子系统+Platform总线
linux·服务器·arm开发·数据库·单片机
上海合宙LuatOS10 小时前
LuatOS核心库API——【audio 】
java·网络·单片机·嵌入式硬件·物联网·音视频·硬件工程