LCD多层菜单的实现

下面我们就模仿手机菜单为例进行说明,首先需要说明几点:
1. 本例只有5个按键,所以没有退出按键,退出需要通过函数实现。
2.本例液晶只可以显示4行汉子,每行显示8个汉字(128*64),所以一行显示标题,3行实现菜单显示和翻滚。
3.光标所以项反白显示。
4.对于按键与显示等,本例不在说明,只说明菜单实现方式。
// 按键值定义
#define KV_NO                      (0x00)          // 无
#define KV_UP                      (0x02)          // 上
#define KV_DN                      (0x04)          // 下
#define KV_MD                      (0x08)          // 中
#define KV_LF                      (0x10)          // 左
#define KV_RT                      (0x20)          // 右


/**************************************************************************************
* Variable definition                                               
**************************************************************************************/
// 菜单参数
typedef struct _MENU_PRMT
{
     uint8 ExitMark;             // 退出菜单(0-不退出,1-退出)
     uint8 Cursor;             // 光标值(当前光标位置)
     uint8 PageNo;             // 菜单页(显示开始项)
     uint8 Index;             // 菜单索引(当前选择的菜单项)
     uint8 DispNum;             // 显示项数(每页可以现在菜单项)
     uint8 MaxPage;             // 最大页数(最大有多少种显示页)
} MENU_PRMT;

//------------------------------------------------------------------------------------
// 菜单执行
typedef struct _MENU_TABLE
{
     uint8 *MenuName;            // 菜单项目名称
     void  (*ItemHook)(void);                // 要运行的菜单函数
} MENU_TABLE;
//----------------------------------   主菜单   ---------------------------------------
MENU_PRMT  GSetPrmt;                   // 常规设置参数
MENU_TABLE GeneralSet[] =                        // 常规设置
{
     {"1. 情景模式     ", Menu_Profile     },                // 情景模式
     {"2. 时间与日期   ", Menu_SetClock    },                // 时间与日期
     {"3. 语言         ", Menu_Null        },                // 选择语言
     {"4. 话机设置     ", Menu_Null        },                // 话机设置
     {"5. 语音设置     ", Menu_Null        },                // 语音设置
     {"6. 安全设置     ", Menu_Null        },                // 安全设置
     {"7. 网络设置     ", Menu_Null        },                // 网络设置
     {"8. 个人快捷设置 ", Menu_Null        },                // 个人快捷设置
     {"9. 恢复出厂设置 ", Menu_Null        },                // 恢复出厂设置
     {"10.退出菜单     ", Menu_Null        },                // 退出菜单
};

//-----------------------------------   二级菜单  -------------------------------------
MENU_PRMT  ProfilePrmt;                   // 情景模式参数
MENU_TABLE Profile[] =                            // 情景模式
{
     {"1. 标准         ", Menu_Null        },                   // 标准
     {"2. 会议         ", Menu_Null        },                   // 会议
     {"3. 户外         ", Menu_Null        },                   // 户外
     {"4. 振动         ", Menu_Null        },                   // 振动
     {"5. 耳机         ", Menu_Null        },                   // 耳机
     {"6. 蓝牙模式     ", Menu_Null        },                   // 蓝牙模式
     {"7. 离线模式     ", Menu_Null        },                   // 离线模式
     {"8. 退出菜单     ", Menu_ExitProfile },                   // 退出菜单
};

MENU_PRMT  ClockPrmt;                         // 时间与日期参数
MENU_TABLE Clock[] =                            // 时间与日期
{
     {"1. 时间/日期设置", Menu_Null        },                   // 时间/日期设置
     {"2. 格式设置     ", Menu_Null        },                   // 格式设置 
     {"3. 设置城市     ", Menu_Null        },                   // 设置城市
     {"4. 时区与时间   ", Menu_Null        },                   // 时区与时间
     {"5. 退出时钟设置 ", Menu_ExitClockSet},       // 退出时钟设置
};
/**************************************************************************************
* FunctionName   : Menu_Null()
* Description    : 空函数
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void Menu_Null(void)
{
    ;
}
/**************************************************************************************
* FunctionName   : Menu_KeySan()
* Description    : 获取按键值
* EntryParameter : None
* ReturnValue    : 返回按键值
**************************************************************************************/
uint8 Menu_KeySan(void)
{
    uint8 key = KV_NO;
    key = KeyGetValue();                               // 获取按键
    if (key != KV_NO)
    {
        BuzzerSound(1);                       // 有键按下,响一声
        while(KeyGetValue() != KV_NO)                   // 等待按键释放
        {
            ;
        }
    }
    return key;
}
/**************************************************************************************
* FunctionName   : Menu_PrmtInit()
* Description    : 初始化菜单参数
* EntryParameter : prmt - 菜单参数, num - 显示项, page - 显示页
* ReturnValue    : None
**************************************************************************************/
void Menu_PrmtInit(MENU_PRMT *prmt, uint8 num, uint8 page)
{
    prmt->ExitMark = 0;                     // 清除退出菜单标志
prmt->Cursor   = 0;                     // 光标清零
prmt->PageNo   = 0;                     // 页清零
prmt->Index    = 0;                     // 索引清零
prmt->DispNum  = num;                    // 页最多显示项目数
prmt->MaxPage  = page;                    // 最多页数
}
/**************************************************************************************
* FunctionName   : Menu_Display()
* Description    : 显示菜单
* EntryParameter : page - 显示页,dispNum - 每一页的显示项,cursor - 光标位置
* ReturnValue    : None
**************************************************************************************/
void Menu_Display(MENU_TABLE *menu, uint8 page, uint8 dispNum, uint8 cursor)
{
uint8 i;
for (i=0; i<dispNum; i++)
{
if (cursor == i)
{
LCMDisplayStrRvs(0, (i+1)*2, menu[page+i].MenuName);            // 反白显示菜单项
}
else
{
LCMDisplayStr(0, (i+1)*2, menu[page+i].MenuName);             // 显示菜单项  
}
}
}

/**************************************************************************************
* FunctionName   : Menu_Move()
* Description    : 菜单移动
* EntryParameter : prmt - 菜单参数, key - 按键值
* ReturnValue    : 有确认返回0,否则返回1
**************************************************************************************/
uint8 Menu_Move(MENU_PRMT *prmt, uint8 key)
{
    uint8 rValue = 1;

    switch (key) 
    {
        case KV_UP:                   // 向上
            if (prmt->Cursor != 0)                       // 光标不在顶端
            {
                prmt->Cursor--;                        // 光标上移
            }
            else                        // 光标在顶端
            {
                if (prmt->PageNo != 0)                      // 页面没有到最小
                {
                    prmt->PageNo--;                       // 向上翻
                }
                else
                {
                    prmt->Cursor = prmt->DispNum-1;                      // 光标到底
                    prmt->PageNo = prmt->MaxPage-1;                  // 最后页
                }
            }
            break;

        case KV_DN:                   // 向下
            if (prmt->Cursor < prmt->DispNum-1)                          // 光标没有到底,移动光标
            {
                prmt->Cursor++;                        // 光标向下移动
            }
            else                                                         // 光标到底
            {
                if (prmt->PageNo < prmt->MaxPage-1)                      // 页面没有到底,页面移动
                {
                    prmt->PageNo++;                       // 下翻一页
                }
                else                                                     // 页面和光标都到底,返回开始页
                {
                    prmt->Cursor = 0;
                    prmt->PageNo = 0;
                }
            }
        break;

        case KV_MD:                   // 确认 
            prmt->Index = prmt->Cursor + prmt->PageNo;                   // 计算执行项的索引
            rValue = 0;
            break;

        case KV_LF:                   // 左键跳到顶部
            prmt->Cursor = 0;
            prmt->PageNo = 0;
            break;

        case KV_RT:                   // 右键跳到底部
            prmt->Cursor = prmt->DispNum-1;                              // 光标到底
            prmt->PageNo = prmt->MaxPage-1;                          // 最后页
            break;

        default:break;
    } 
    return rValue;                          // 返回执行索引
}
/**************************************************************************************
* FunctionName   : Menu_Process()
* Description    : 处理菜单项
* EntryParameter : menuName - 菜单名称,prmt - 菜单参数,table - 菜单表项, num - 菜单项数
* ReturnValue    : None
**************************************************************************************/
void Menu_Process(uint8 *menuName, MENU_PRMT *prmt, MENU_TABLE *table, uint8 num)
{
    uint8 key;
    Menu_PrmtInit(prmt, PAGE_DISP_NUM, num-PAGE_DISP_NUM+1);                          // 显示项数和页数设置
    do
    {
        LCMDisplayStr(0, 0, menuName);                                   // 菜单标题显示
        Menu_Display(table, prmt->PageNo, prmt->DispNum, prmt->Cursor);               // 显示菜单项
        key = Menu_KeySan();                      // 获取按键
        if (Menu_Move(prmt, key) == 0x00)                                  // 菜单移动
        {
            LCMClearScreen(LCM_WHITE);                       // 清屏
            table[prmt->Index].ItemHook();                               // 执行相应项
        }
    } while (prmt->ExitMark == 0);
}
/**************************************************************************************
* FunctionName   : MenuGeneralSet()
* Description    : 常规设置
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void MenuGeneralSet(void)
{
    uint8 menuNum;
    menuNum = sizeof(GeneralSet)/sizeof(GeneralSet[0]);         // 菜单项数
    Menu_Process(" -= 常规设置 =- ", &GSetPrmt, GeneralSet, menuNum);
}
/**************************************************************************************
* FunctionName   : Menu_Profile()
* Description    : 情景模式
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void Menu_Profile(void)
{
    uint8 menuNum;
    menuNum = sizeof(Profile)/sizeof(Profile[0]);         // 菜单项数
    Menu_Process(" -= 情景模式 =- ", &ProfilePrmt, Profile, menuNum);
}
/**************************************************************************************
* FunctionName   : Menu_ExitProfile()
* Description    : 退出情景模式
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void Menu_ExitProfile(void) 
{
    ProfilePrmt.ExitMark = 0x01;         // 退出情景模式
    LCMClearScreen(LCM_WHITE);             // 清屏 
} 

/**************************************************************************************
* FunctionName   : Menu_SetClock()
* Description    : 时间与日期设置
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void Menu_SetClock(void)
{
    uint8 menuNum;
    menuNum = sizeof(Clock)/sizeof(Clock[0]);         // 菜单项数
    Menu_Process(" -= 时间日期 =- ", &ClockPrmt, Clock, menuNum);
}
/**************************************************************************************
* FunctionName   : Menu_ExitClockSet()
* Description    : 退出日期与时钟
* EntryParameter : None
* ReturnValue    : None
**************************************************************************************/
void Menu_ExitClockSet(void) 
{
    ClockPrmt.ExitMark = 0x01;             // 退出时钟设置
    LCMClearScreen(LCM_WHITE);             // 清屏 
} 


TFTLCD多级菜单是一种在液晶显示屏上实现多层菜单系统。它通常用于嵌入式系统或电子设备中,方便用户进行操作和选择。 实现TFTLCD多级菜单的基本步骤如下: 1. 初始化:首先,你需要初始化TFTLCD屏幕和相关的硬件。这包括设置屏幕分辨率、初始化通信接口(如SPI或I2C),以及加载所需的字体和图标。 2. 设计菜单结构:根据你的需求,设计多级菜单的结构。每个菜单项可以包括菜单名称、图标、子菜单等。可以使用树状结构来表示菜单的层级关系。 3. 显示菜单:在屏幕上显示主菜单,并等待用户的输入。用户可以通过按键、触摸屏或其他输入方式进行选择。 4. 处理用户输入:根据用户的输入,更新当前菜单的状态。如果用户选择了某个菜单项,可以进入相应的子菜单。如果用户选择返回上一级菜单,则返回上一级。 5. 更新显示:在每次用户输入后,更新屏幕上显示的菜单内容。根据当前菜单的状态,动态地显示菜单项、光标位置等。 6. 执行操作:当用户选择了最终的菜单项时,执行相应的操作。这可以是调用特定功能、设置参数等。 7. 循环处理:重复步骤3至6,直到用户退出菜单系统。 需要注意的是,TFTLCD多级菜单的具体实现方式可能会因硬件平台、开发语言和框架等不同而有所差异。你可以根据自己的需求和环境选择合适的方法来实现
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值