12864液晶文字菜单的实现

文章开头先上传几张图片供参考:
12864液晶文字菜单的实现_第1张图片
12864液晶文字菜单的实现_第2张图片
12864液晶文字菜单的实现_第3张图片
12864液晶文字菜单的实现_第4张图片

菜单最初显示是这样的,下面上代码。代码布防其实并发全部又本人所写,但大部分代码本人都进行过
修改。

#define MENULEVEL 2 //当前菜单表个数
#define OPTIONMETE 19 //当前选项个数,包括一个特别功能选项
//#define SIZE sizeof(Address_buf)
//————————————-
//
// 菜单结构定义
//
//————————————-
struct Option{
unsigned char KeyLevel; //菜单选项所属菜单表号
unsigned char EnterIndex; //选项进入索引号
unsigned char CancelIndex; //选项退出索引号
unsigned char KeyWord[16]; //菜单选项文字描述数组
unsigned char WordMete; //菜单选项描述文字字节数
};
//————————————-
//
// 具体菜单选项定义,定义一个结构数组
// 存储在编码区,节省内存RAM
// 功能的进入索引应大于OPTIONMETE
// 在FunctionAction(void)函数的case选项
// 中应定义出索引对应的功能函数。
//————————————-
struct Option sOption[OPTIONMETE] = {
{0,OPTIONMETE-1,0,”设置报警界限”,12}, //0
{0,OPTIONMETE-1,0,”设置报警延时”,12}, //1 //一级菜单
{0,OPTIONMETE-1,0,”设置时钟时间”,12}, //2
{0,OPTIONMETE-1,0,”设置密码开关”,12}, //3
{0,6,0,”系统版本”,8}, //4
{0,OPTIONMETE-1,0,”退出菜单”,8}, //5

{1,OPTIONMETE-1,3,"****硬件****",12},           //6        
{1,OPTIONMETE-1,3,"GSDC_V1.5",9},               //7      
{1,OPTIONMETE-1,3,"****软件****",12},           //8        
{1,OPTIONMETE-1,3,"GUI:",4},                    //9//“系统版本”选项二级菜单
{1,OPTIONMETE-1,3,"Worm_V0.95",10},             //10         
{1,OPTIONMETE-1,3,"Program:",8},                //11         
{1,OPTIONMETE-1,3,"GSDC_Program",12},           //12        
{1,OPTIONMETE-1,3,"V1.6.1",6},                  //13         
{1,OPTIONMETE-1,3,"****服务****",12},           //14       
{1,OPTIONMETE-1,3," TCP终端设备",12},           //15         
{1,OPTIONMETE-1,3,"客服电话:",10},             //16      
{1,OPTIONMETE-1,3,"          ",10},             //17        

{0,0,0,"",0}                                    //18//特殊,无操作索引

};
//————————————–
//
// 菜单表分类数组
//
//————————————–
unsigned char Level[MENULEVEL][3] = {//每层表单对应 开始索引号、结束索引号、选项数目
{0,5,6},
{6,17,12},
};
unsigned char FirstLineDisIndex = 0; //屏幕第一行显示的索引号
unsigned char SelectLine = 1; //当前选择的行
unsigned char SelectIndex = 0; //当前选定行对应的索引号
unsigned char LastIndex = 0; //进入功能函数前的索引号,判断具体功能使用
/此部分为菜单的预定义部分应放在文件的最开头/
//—————————————-
//
// 判断当前索引是否是表单第一项功能函数
// 函数原形:u8 MenuLevelStart (void);
// 没有参数,返回Bit标志,是第一项返回1,不是返回0
// 调用方式:u8 MenuLevelStart (void);
//
//—————————————-
u8 MenuLevelStart (void) //判断当前索引是否为当前层第一个选项
{
unsigned char i = MENULEVEL;
do
{
i–;
if(SelectIndex == Level[i][0]) return 1;
}while(i);
return 0;
}
//—————————————-
//
// 判断当前索引是否是表单最后一项功能函数
// 函数原形:u8 MenuLevelEnd (void);
// 没有参数,返回Bit标志,是最后一项返回1,不是返回0
// 调用方式:u8 MenuLevelEnd (void);
//
//—————————————-
u8 MenuLevelEnd (void)
{
unsigned char i = MENULEVEL;
do
{
i–;
if(SelectIndex == Level[i][1]) return 1;
}while(i);
return 0;
}
//—————————————-
//
// 菜单上移一项函数
// 函数原形:void MenuUpOneOption (void);
// 没有参数,没有返回值
// 调用方式:void MenuUpOneOption (void);
//
//—————————————-
void MenuUpOneOption (void)
{
if(MenuLevelStart ()) //如果当前为表单第一项
{
if(Level[sOption[SelectIndex].KeyLevel][2]>=4) //并且表单中选项数目大于等于4个
{
FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][1]-3;
//第一行显示索引号为倒数第四项
SelectIndex = Level[sOption[SelectIndex].KeyLevel][1]; //选择索引为表单最后一项
SelectLine = 4; //标记选择行为第四行
DIS12864M (); //刷新屏幕显示
}
else //如果选项数目并不大于四个
{
SelectIndex = Level[sOption[SelectIndex].KeyLevel][1]; //选择索引为当前表单最后一个
SelectLine = Level[sOption[SelectIndex].KeyLevel][2]; //显示行表单数目(最后一个)
DIS12864M (); //刷新屏幕显示
}
}
else //如果当前不是开始索引
{
if(SelectLine==1) //并且已经在屏幕最上边一行
{
FirstLineDisIndex–; //显示索引上移
SelectIndex–; //选择索引自减
SelectLine = 1; //选择行还是第一行
DIS12864M (); //刷新屏幕
}
else //如果不是第一行
{
SelectLine–; //选择行自减
SelectIndex–; //选择索引自减
DIS12864M (); //刷新屏幕显示
}
}
}
//—————————————-
//
// 菜单下移一项函数
// 函数原形:void MenuDownOneOption (void);
// 没有参数,没有返回值
// 调用方式:void MenuDownOneOption (void);
//
//—————————————-
void MenuDownOneOption (void)
{
if(MenuLevelEnd ()) //如果当前是表单最后一个索引
{
FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][0];
//第一行显示索引为表单第一个选项
//选择索引为表单第一个选项索引
SelectLine = 1; //选择行为第一行
DIS12864M (); //刷新显示
}
else //如果不是最后的索引
{
if(SelectLine!=4) //如果当前不是屏幕最底行
{
SelectIndex++; //选择索引自加
SelectLine++; //选择行下移
SetALineReverse (SelectLine); //刷新选择行
DIS12864M (); //刷新显示
}
else //如果是屏幕最低行
{
FirstLineDisIndex++; //第一行显示下移
SelectIndex++; //选择索引自加
DIS12864M(); //刷新显示
}
}
}

//—————————————-
//
// 某些功能函数,完成菜单中的具体功能
//
//—————————————-
void password_authentification(void) //登录密码校验函数
{
u8 pallword_sum=0;
u8 pallword_value[6]={‘1’,’2’,’3’,’4’,’5’,’6’};
u8 pallword[6];
u8 pal_sum=0;
u8 i=0;
LCD_Chinese_disp(0,0,”—-登录界面—-<”);
LCD_Chinese_disp(1,0,”请输入6 位密码 <”); //
LCD_Chinese_disp(2,0,”按END 键结束 <”);
LCD_Chinese_disp(3,0,” <”);
delay_ms(500);
while(1)
{
pallword_sum=0;
if((KEY_Scan()!=0x00)&&(KEY_Scan()!=’D’)&&(KEY_Scan()!=’C’))
{
pallword[pal_sum]=KEY_Scan();
LCD_Chinese_disp(3,pal_sum,”* <”);
delay_ms(300);
pal_sum++;
if(pal_sum>5)
{
pal_sum=0;
}

    }else if(KEY_Scan()=='D')    //按下确认键
    {

        for(i=0;i<6;i++)
        {
            if(pallword[i]==pallword_value[i])
            {
                pallword_sum++; 
            }               
            pallword[i] = ' ';  
        }
        pal_sum = 0;
        if(pallword_sum == 6)
        {
            pwr_sig = 1;
            DIS12864M ();             //刷新菜单
            break;                    //六位密码全部正确
        }else                         //密码不正确处理
        {
            LCD_Chinese_disp(3,0,"操作密码错误!  <");
            delay_ms(1000);
            LCD_Chinese_disp(3,0,"                <");          
        } 
    }else if(KEY_Scan()=='C')         //按下退出键
    {
        pwr_sig = 0;
        break;                      //输入密码时按退出键
    }           
}   

}

void shut_down(void) //菜单“退出系统”选项的功能实现
{
FirstLineDisIndex = 0; //屏幕第一行显示的索引号
SelectLine = 1; //当前选择的行
SelectIndex = 0; //当前选定行对应的索引号
LastIndex = 0; //进入功能函数前的索引号,判断具体功能使用
down = 1;
}

//—————————————-
//
// 具体功能散转函数
// 函数原形:void FunctionAction
// 没有参数,没有返回值
// 调用方式:void FunctionAction (void);
//
//—————————————-
void FunctionAction (void) ////////////////////////////////
{
switch(LastIndex) //根据进入前的索引判断具体函数
{
case 5:shut_down(); break; //退出菜单功能索引

    case 0:Arm_SEN_set(); break;          //报警灵敏度设置         
    case 1:Arm_Delay_set(); break;         //报警延时设置     
    case 2:Time_set(); break;             //时间设置功能索引    
    case 3:Password_switch_set(); break;     //密码校验开关

    default:shut_down();break;             //如果没有具体操作,显示没有这个功能
}

}
//—————————————-
//
// 进入某项功能函数
// 函数原形:void MenuEnterOption (void);
// 没有参数,没有返回值
// 调用方式:void MenuEnterOption (void);
//
//—————————————-
void MenuEnterOption (void)
{
LastIndex = SelectIndex; //标记进入前的索引号(以便判断具体功能)
SelectIndex = sOption[SelectIndex].EnterIndex;
//更新选择索引为之前索引号对应进入索引
if(SelectIndex != OPTIONMETE-1) //如果当前索引不是功能选择索引 /////////////////////////////////////////////////////////////
{
//第一行显示为进入表单第一项
SelectLine = 1; //设定第一行为选择行
DIS12864M (); //刷新菜单
}
else FunctionAction (); //如果是功能选择项,进入功能分支判断函数
}
//—————————————-
//
// 菜单退出功能函数
// 函数原形:void MenuCancelOption (void);
// 没有参数,没有返回值
// 调用方式:void MenuCancelOption (void);
//
//—————————————-
void MenuCancelOption (void)
{
if(SelectIndex != OPTIONMETE-1) //如果不是从功能返回
SelectIndex = sOption[SelectIndex].CancelIndex; //选择索引为选项返回索引
else //如果是从功能返回
SelectIndex = LastIndex; //索引等于进入前保存索引
if(Level[sOption[SelectIndex].KeyLevel][2]>=4) //如果返回表单选项数目大于4个
{
if(SelectIndex > Level[sOption[SelectIndex].KeyLevel][1]-3)
//根据返回选项确定显示首项
{
FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][1]-3;
SelectLine = 4-(Level[sOption[SelectIndex].KeyLevel][1]-SelectIndex);
DIS12864M (); //刷新显示
}
else //一般显示方式
{
FirstLineDisIndex = SelectIndex; //第一行显示索引
SelectLine = 1; //选择第一行
DIS12864M (); //刷新菜单
}
}
else //如果返回表单选项数目不足4个
{
FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][0];
//第一行显示索引为表单第一项
//选择行标志为当前选择索引对应行
DIS12864M (); //刷新菜单
}
}
//—————————————-
//
// 菜单操作按键处理散转函数
// 函数原形:void KeyCodeAction (unsigned char KeyCode);
// 键码作为参数,没有返回值
// 调用方式:void KeyCodeAction (unsigned char KeyCode);
// 实际使用应根据自己的按键重新编写case项
//
//—————————————-
void KeyCodeAction (unsigned char KeyCode)
{
switch (KeyCode)
{
case ‘*’:
{
beep_bi(); //蜂鸣器响一声
MenuUpOneOption();
delay_ms(100);
break; //如果是向上按键,则菜单向上,以下类似
}
case ‘#’:
{
beep_bi(); //蜂鸣器响一声
MenuDownOneOption();
delay_ms(100);
break;
}
case ‘D’:
{
beep_bi_bi(); //蜂鸣器响两声
MenuEnterOption();
delay_ms(100);
break;
}
case ‘C’:
{
beep_bi(); //蜂鸣器响一声
MenuCancelOption();
delay_ms(100);
break;
}
default: break;
}
}
//—————————————-
//
// 菜单更新函数
// 函数原形:void MenuReflash (void);
// 没有参数,没有返回值
// 调用方式:void MenuReflash (void);
// 实际应配合自己的按键编码获取程序使用
//
//—————————————-
void MenuReflash (void)
{
unsigned char Keytemp; //保存按键编码变量
Keytemp = KEY_Scan(); //保存按键编码
if(Keytemp!=0x00) //如果按键编码有效
{
KeyCodeAction(Keytemp); //根据按键说明字母散转
down_sum = 2000; //如果进入菜单后有按键操作,则重新计时。
}

}

void enter_menu(void)
{
u8 pallword_sum=0;
u8 pallword_value[6]={‘1’,’2’,’3’,’4’,’5’,’6’};
u8 pallword[6];
u8 pal_sum=0;
u8 i=0;
u16 esc_time_num = 0;

if(Password_SW)             //判断是否需要输入密码1时需要输入,0时不需要输入。
{
    if((KEY_Scan() == '0')||(KEY_Scan() == '1')||(KEY_Scan() == '2')
    ||(KEY_Scan() == '3')||(KEY_Scan() == '4')||(KEY_Scan() == '5')
    ||(KEY_Scan() == '6')||(KEY_Scan() == '7')||(KEY_Scan() == '8')
    ||(KEY_Scan() == '9'))
    {
        while(1)
        {
            BL_set_L;                                 //打开背光    
            if((KEY_Scan()!=0x00)&&(KEY_Scan()!='D')&&(KEY_Scan()!='C')&&(KEY_Scan()!='A')&&(KEY_Scan()!='B'))
            {       
                pallword[pal_sum]=KEY_Scan();
                beep_bi();                          //蜂鸣器响一声 
                LCD_Chinese_disp(0,0,"----登录界面----<");
                LCD_Chinese_disp(1,0,"请输入6 位密码  <");            //
                LCD_Chinese_disp(2,0,"按END 键结束    <");
                if(pal_sum == 0)
                {
                    LCD_Chinese_disp(3,pal_sum,"*               <");    
                }else
                {
                    LCD_Chinese_disp(3,pal_sum,"* <");
                }   

                delay_ms(300);
                pal_sum++;
                if(pal_sum>5)
                {
                    pal_sum=0;
                }
                esc_time_num = 0;            //清楚自动退出密码输入界面的计时。

            }else if(KEY_Scan()=='A')
            {
                for(i=0;i<6;i++)                //检查6位密码是否正确
                {
                    if(pallword[i]==pallword_value[i])
                    {
                        pallword_sum++; 
                    }               
                    pallword[i] = ' ';  
                }
                pal_sum = 0;
                if(pallword_sum == 6)        //如果全部都正确执行布防命令
                {
                    //////////////////////////////////////////////////////////////////
                    break;
                }else 
                {
                    BL_set_L;                      //打开背光   
                    LCD_Chinese_disp(0,0,"----登录界面----<");
                    LCD_Chinese_disp(1,0,"请输入6 位密码  <");            //
                    LCD_Chinese_disp(2,0,"按END 键结束    <");
                    LCD_Chinese_disp(3,0,"密码错误!      <");
                    beep_du();                        //长警告音
                    delay_ms(1000);
                    delay_ms(1000);

                    break;  
                }   
            }else if(KEY_Scan()=='B')
            {
                for(i=0;i<6;i++)            //检查6位密码是否正确
                {
                    if(pallword[i]==pallword_value[i])
                    {
                        pallword_sum++; 
                    }               
                    pallword[i] = ' ';  
                }
                pal_sum = 0;
                if(pallword_sum == 6)   //如果全部都正确执行布防命令
                {
                    /////////////////////////////////////////////////////////////////////////
                    break;  
                }else 
                {
                    BL_set_L;                             //打开背光    
                    LCD_Chinese_disp(0,0,"----登录界面----<");
                    LCD_Chinese_disp(1,0,"请输入6 位密码  <");    //
                    LCD_Chinese_disp(2,0,"按END 键结束    <");
                    LCD_Chinese_disp(3,0,"密码错误!      <");
                    beep_du();                        //长警告音
                    delay_ms(1000);
                    delay_ms(1000);

                    break;  
                }   
            }else if(KEY_Scan()=='C')
            {

                beep_du();                               //长警告音

                break;      
            }else if(KEY_Scan()=='D')
            {
                for(i=0;i<6;i++)            //检查6位密码是否正确
                {
                    if(pallword[i]==pallword_value[i])
                    {
                        pallword_sum++; 
                    }               
                    pallword[i] = ' ';  
                }
                pal_sum = 0;
                if(pallword_sum == 6)                //如果全部都正确执行布防命令
                {
                    beep_bi_bi();                          //蜂鸣器响两声
                    BL_set_L;                              //进入菜单时打开背光
                    DIS12864M ();                          //刷新菜单
                    delay_ms(50);
                    while(1)
                    {   
                        MenuReflash();                     //进入主菜单 
                        down_sum--;
                        if(down_sum<=0) //如果进入菜单20秒无操作,则自动退出菜单。
                        {
                            shut_down();
                            down_sum = 2000;    
                        }   
                        if(down)
                        {
                            delay_ms(100);
                            down = 0;
                            break;
                        }
                        delay_ms(10);       
                    }
                    break;
                }else 
                {
                    LCD_Chinese_disp(0,0,"----登录界面----<");
                    LCD_Chinese_disp(1,0,"请输入6 位密码  <");            //
                    LCD_Chinese_disp(2,0,"按END 键结束    <");
                    LCD_Chinese_disp(3,0,"密码错误!      <");
                    beep_du();                            //长警告音
                    delay_ms(1000);
                    delay_ms(1000);

                    break;  
                }       
            }else               //如果长时间保持无按键按下时退回到主界面 
            {
                if(esc_time_num == 2000)
                {
                    esc_time_num = 0;

                    break;  
                }else
                {
                    esc_time_num++; 
                    delay_ms(10);
                }

            }
        }
    }       
}else                //不需要输入密码时菜单和快捷撤布防的命令处理
{
    if(KEY_Scan()=='A')
    {
        beep_bi_bi();                               //蜂鸣器响两声
        BL_set_L;                                   //打开背光

    }else if(KEY_Scan()=='B')
    {
        beep_bi_bi();                          //蜂鸣器响两声
        BL_set_L;                                   //打开背光

    }else if(KEY_Scan()=='C')
    {
        beep_du();                              //长警告音
        BL_set_L;                                   //打开背光
    }else if(KEY_Scan()=='D')
    {
        beep_bi_bi();                          //蜂鸣器响两声
        BL_set_L;                              //进入菜单时打开背光
        DIS12864M ();                          //刷新菜单
        while(1)
        {   
            MenuReflash();                     //进入主菜单 
            down_sum--;
            if(down_sum<=0)     //如果进入菜单20秒无操作,则自动退出菜单。
            {
                shut_down();
                down_sum = 2000;    
            }   
            if(down)
            {
                delay_ms(100);
                down = 0;
                break;
            }
            delay_ms(10);       
        }
        LCD_clear();                      //清空液晶屏显示                 
    }       
}   

}

如果需要移植此段代码的朋友需要注意几个函数,一个是液晶显示刷新函数,一个是指示器显示函数。
本人这两个函数是这样写的:
//—————————————-
//
// 刷新菜单功能函数
// 函数原形:void DIS12864M (void);
// 没有参数,没有返回值
// 调用方式:void DIS12864M (void);
//
//—————————————-
void DIS12864M (void)
{
unsigned char LineMete = Level[sOption[SelectIndex].KeyLevel][2]; //循环量,显示行数
write_com(0x30); //进入液晶普通指令模式
write_com(0x01); //清屏
delay_ms(100);
SetALineReverse(SelectLine); //填充所需反白
do //分别显示各行菜单项
{
LCD_Chinese_disp(0,1,sOption[FirstLineDisIndex].KeyWord);
if(LineMete == 0) break;

      LCD_Chinese_disp(1,1,sOption[FirstLineDisIndex+1].KeyWord);
      if(LineMete == 0) break;

      LCD_Chinese_disp(2,1,sOption[FirstLineDisIndex+2].KeyWord);
      if(LineMete == 0) break;

      LCD_Chinese_disp(3,1,sOption[FirstLineDisIndex+3].KeyWord);
}while(0);
SetALineReverse(SelectLine);           //填充所需反白 

}

你可能感兴趣的:(单片机,代码)