单片机 LCD 菜单架构

 

参考了网上一些资料,写了一个还能用的单片机 LCD显示菜单,改起来还比较简单:

其中 MenuItem 中 itemIdx 可以不要,没有什么作用。

pSelectItem 也可以不要的。和 pCurItem 有点重复了。

实现效果如下:可以显示三级菜单。

 

IMG_20130930_145625IMG_20130930_145643IMG_20130930_145700IMG_20130930_145709IMG_20130930_145718

 

//menu.h

#define LCD_MaxItem 4
typedef struct str_MenuItem
{
    uint8_t itemIdx;
    uint8_t itemCnt;
    char * dispString;
    void (*itemFunc)();
    struct str_MenuItem *pChildMenu;
    struct str_MenuItem *pParentMenu;
}MenuItem;

enum MenuItemIdxEnum{One=1,Two,Three,Four,Five,Six,One_One,One_Two,One_Three,
    One_Four,One_Five,One_Six,Two_One,Two_Two,One_One_One,One_One_Two,One_One_Three,
    One_One_Four,One_One_Five,One_One_Six};

void menuInit();
void showEnterMsg();
void showCurItem();
void showChildItem(); //显示下一级菜单
void showParentItem();
void showItems();
extern MenuItem * pCurItem;
extern MenuItem * pSelectItem;
extern MenuItem * pDispStartItem;
extern MenuItem * pCurMenuStartItem;

//menu.c

#include "menu.h"
#include <stdlib.h>

#define FirstMenuItemNum 6
#define SecondMenuItemNum 6
#define ThirdMenuItemNum 2
#define ForthMenuItemNum 6
#define MIN(x,y)\
    ( (x)<(y) ?  x:y )

MenuItem firstMenu[FirstMenuItemNum];
MenuItem secondMenu[SecondMenuItemNum];
MenuItem thirdMenu[ThirdMenuItemNum];
MenuItem forthMenu[ForthMenuItemNum];

MenuItem * pCurItem;
MenuItem * pSelectItem;
MenuItem * pDispStartItem;
MenuItem * pCurMenuStartItem;
#define SaveMaxLevel 10
MenuItem * pArrCurMenuStart[SaveMaxLevel];
MenuItem * pArrDispStart[SaveMaxLevel];
uint8_t arrCntSaveMenu=0;

MenuItem firstMenu[]=
{
    {One,FirstMenuItemNum,"one",showChildItem,secondMenu,NULL},
    {Two,FirstMenuItemNum,"two",showChildItem,thirdMenu,NULL},
    {Three,FirstMenuItemNum,"three",showEnterMsg,NULL,NULL},
    {Four,FirstMenuItemNum,"four",showEnterMsg,NULL,NULL},
    {Five,FirstMenuItemNum,"five",NULL,NULL,NULL},
    {Six,FirstMenuItemNum,"six",NULL,NULL,NULL}
};
MenuItem secondMenu[]=
{
    {One_One,SecondMenuItemNum,"oneone",NULL,NULL,firstMenu},
    {One_Two,SecondMenuItemNum,"onetwo",NULL,NULL,firstMenu},
    {One_Three,SecondMenuItemNum,"onethree",showChildItem,forthMenu,firstMenu},
    {One_Four,SecondMenuItemNum,"onefour",NULL,NULL,firstMenu},
    {One_Five,SecondMenuItemNum,"onefive",NULL,NULL,firstMenu},
    {One_Six,SecondMenuItemNum,"onesix",NULL,NULL,firstMenu}
};
MenuItem thirdMenu[]=
{
    {Two_One,ThirdMenuItemNum,"twoone",NULL,NULL,&firstMenu[1]},
    {Two_Two,ThirdMenuItemNum,"twotwo",NULL,NULL,&firstMenu[1]}
};
MenuItem forthMenu[]=
{
    {One_One_One,ForthMenuItemNum,"oneoneone",showEnterMsg,NULL,&secondMenu[2]},
    {One_One_Two,ForthMenuItemNum,"oneonetwo",showEnterMsg,NULL,&secondMenu[2]},
    {One_One_Three,ForthMenuItemNum,"oneonethree",showEnterMsg,NULL,&secondMenu[2]},
    {One_One_Four,ForthMenuItemNum,"oneonefour",showEnterMsg,NULL,&secondMenu[2]},
    {One_One_Five,ForthMenuItemNum,"oneonefive",showEnterMsg,NULL,&secondMenu[2]},
    {One_One_Six,ForthMenuItemNum,"oneonesix",showEnterMsg,NULL,&secondMenu[2]}
};
void menuInit()
{
    memset(pArrCurMenuStart,0,SaveMaxLevel);
    memset(pArrDispStart,0,SaveMaxLevel);
    arrCntSaveMenu=0;

    pCurItem=&firstMenu[0];
    pSelectItem=pCurItem;
    pCurMenuStartItem=&firstMenu[0];
    pDispStartItem=&firstMenu[0];
}

void showEnterMsg()
{
    char msg[20];
    lcdSerialClear();
    lcdSerialSetCursor(6,0);
    sprintf(msg,"item %d",pSelectItem->itemIdx);
    lcdSerialWriteString(msg);
    delay_ms(2000);
    showCurItem();
}
void showCurItem()
{
    showItems();
}
void showChildItem() //显示下一级菜单
{
//    int i;
//    MenuItem *pItem;
    if(NULL==pCurItem->pChildMenu) //
        return;
    if(arrCntSaveMenu >= SaveMaxLevel)
        return;
    pArrCurMenuStart[arrCntSaveMenu]=pCurMenuStartItem;
    pArrDispStart[arrCntSaveMenu]=pDispStartItem;
    arrCntSaveMenu++;

    pCurItem=pCurItem->pChildMenu;
    pCurMenuStartItem=pCurItem;
    pSelectItem=pCurItem;
    pDispStartItem=pCurItem;
    showItems();
}
void showParentItem()
{
    if(NULL==pCurItem->pParentMenu)
        return;
    if(arrCntSaveMenu <=0)
        return;
    arrCntSaveMenu--;

    pCurItem=pCurItem->pParentMenu;
    pCurMenuStartItem=pArrCurMenuStart[arrCntSaveMenu];
    pSelectItem=pCurItem;
    pDispStartItem=pArrDispStart[arrCntSaveMenu];
    showItems();
}
void showItems()
{
    int i;
    MenuItem * pItem;
    lcdSerialClear();
        pItem=pDispStartItem;
    for(i=0;i<MIN(pSelectItem->itemCnt,LCD_MaxItem);i++)
    {
        lcdSerialSetCursor(2,i);
        lcdSerialWriteString(pItem->dispString);
        if(pSelectItem==pItem)
        {
            lcdSerialSetCursor(0,i);
            lcdSerialWriteString("->");
        }
        pItem++;
    }
}

 

//main.c

 

while 循环:

    switch(btnCode)
        {
            case 0x01:
                if(pCurItem - pCurMenuStartItem <(pCurItem->itemCnt-1)) // pCurItem还没有指向最后一项
                {
                    if(pCurItem - pDispStartItem ==(LCD_MaxItem-1)) //显示项超过LCD行数,需整体上移
                    {
                        pDispStartItem++;
                    }
                    pCurItem++;
                }
                pSelectItem=pCurItem;
                showCurItem();
                printf("down\r\n");btnCode=0;
                break;
            case 0x02:
                printf("left\r\n");btnCode=0;
                if(NULL!=pCurItem->pParentMenu)
                {
                    showParentItem();
                }
                break;
            case 0x04:
                printf("center\r\n");btnCode=0;
                
                {
                    if(NULL!=(pCurItem->itemFunc))
                        (*(pCurItem->itemFunc))();
                }
                break;
            case 0x08:
                printf("right\r\n");btnCode=0;
                if(NULL!=pCurItem->pChildMenu)
                    showChildItem();
                break;
            case 0x10:
                if(pCurItem > pCurMenuStartItem)
                {
                    if(pCurItem == pDispStartItem)
                    {
                        pDispStartItem--;
                    }
                    pCurItem--;
                }
                pSelectItem=pCurItem;
                showCurItem();
                printf("up\r\n");btnCode=0;
                break;
            default:
                break;
        }

posted @ 2013-09-30 15:31  tofixer  阅读(1668)  评论(0编辑  收藏  举报