分类:
2010-03-13 18:04:06
有朋友问我要源程序,这个源程序是我最近修改过的最新版本的12864与4*4键盘的人机交互界面,我只给出关键交互界面菜单的源程序,至于12864和4*4键盘的驱动,相信大家都有了。
最新版本的使用反白表示选择行,增加了详细的注释。给需要的朋友一个参考。希望朋友们能写出更好的菜单程序。
//----------------------------------------
// 12864M四行多级菜单
// 文件名称12864menu1。c
// 作者 张子墨
// 版本 0.95
// 最后更新2006/12/16
//----------------------------------------
#include
#include "12864Driver.c"
#define MENULEVEL 7 //当前菜单表个数
#define OPTIONMETE 29 //当前选项个数,包括一个特别功能选项
//-------------------------------------
//
// 菜单结构定义
//
//-------------------------------------
struct Option{
unsigned char KeyLevel; //菜单选项所属菜单表号
unsigned char EnterIndex; //选项进入索引号
unsigned char CancelIndex; //选项退出索引号
unsigned char KeyWord[16]; //菜单选项文字描述数组
unsigned char WordMete; //菜单选项描述文字字节数
};
//-------------------------------------
//
// 具体菜单选项定义,定义一个结构数组
// 存储在编码区,节省内存RAM
//
//-------------------------------------
struct Option code sOption[OPTIONMETE] = {
{0,9,0,"文本功能",8}, //0
{0,16,1,"时间功能",8}, //1
{0,19,2,"温度功能",8}, //2
{0,OPTIONMETE-1,3,"系统检测",8}, //3
{0,OPTIONMETE-1,4,"修改密码",8}, //4
{0,OPTIONMETE-1,5,"帮助说明",8}, //5
{0,OPTIONMETE-1,6,"作者介绍",8}, //6
{0,OPTIONMETE-1,7,"系统版本",8}, //7
{0,OPTIONMETE-1,8,"退出系统",8}, //8
{1,OPTIONMETE-1,0,"输入显示向导",12}, //9
{1,OPTIONMETE-1,0,"新建显示文本",12}, //10
{1,OPTIONMETE-1,0,"文本发送显示",12}, //11
{1,OPTIONMETE-1,0,"删除已存文本",12}, //12
{1,14,0,"输入法设定",10}, //13
{2,OPTIONMETE-1,13,"输入法选择",10}, //14
{2,OPTIONMETE-1,13,"输入法排序",10}, //15
{3,OPTIONMETE-1,1,"设定本机时间",12}, //16
{3,OPTIONMETE-1,1,"发送本机时间",12}, //17
{3,OPTIONMETE-1,1,"与计算机同步时间",16}, //18
{4,23,2,"显示当前温度",12}, //19
{4,OPTIONMETE-1,2,"存储当前温度",12}, //20
{4,OPTIONMETE-1,2,"显示已存温度",12}, //21
{4,OPTIONMETE-1,2,"删除已存温度",12}, //22
{5,25,18,"本机显示",8}, //23
{5,OPTIONMETE-1,19,"子机显示",8}, //24
{6,OPTIONMETE-1,23,"LED 显示",8}, //25
{6,OPTIONMETE-1,23,"数码管显示",10}, //26
{6,OPTIONMETE-1,23,"同时显示",8}, //27
{0,0,0,"",0} //28
};
//--------------------------------------
//
// 菜单表分类数组
//
//--------------------------------------
unsigned char code Level[MENULEVEL][3] = {
{0,8,9}, //每层表单对应开始结束索引号以及选项数目
{9,13,5},
{14,15,2},
{16,18,3},
{19,22,4},
{23,24,2},
{25,27,3}
};
unsigned char FirstLineDisIndex = 0; //屏幕第一行显示的索引号
unsigned char SelectLine = 1; //当前选择的行
unsigned char SelectIndex = 0; //当前选定行对应的索引号
unsigned char LastIndex = 0; //进入功能函数前的索引号,判断具体功能使用
//----------------------------------------
//
// 刷新菜单功能函数
// 函数原形:void DIS12864M (void);
// 没有参数,没有返回值
// 调用方式:void DIS12864M (void);
//
//----------------------------------------
void DIS12864M (void)
{
unsigned char i,LineMete = Level[sOption[SelectIndex].KeyLevel][2]; //循环量,显示行数
SentAIns(0x30); //进入液晶普通指令模式
SentAIns(0x01); //清屏
SetALineReverse (SelectLine); //填充所需反白
do //分别显示各行菜单项
{
SentAIns(0x80);
for(i=0;i
if(--LineMete == 0) break;
SentAIns(0x90);
for(i=0;i
if(--LineMete == 0) break;
SentAIns(0x88);
for(i=0;i
if(--LineMete == 0) break;
SentAIns(0x98);
for(i=0;i
}while(0);
}
//----------------------------------------
//
// 判断当前索引是否是表单第一项功能函数
// 函数原形:bit MenuLevelStart (void);
// 没有参数,返回Bit标志,是第一项返回1,不是返回0
// 调用方式:bit MenuLevelStart (void);
//
//----------------------------------------
bit MenuLevelStart (void) //判断当前索引是否为当前层第一个选项
{
unsigned char i = MENULEVEL;
do
{
i--;
if(SelectIndex == Level[i][0]) return 1;
}while(i);
return 0;
}
//----------------------------------------
//
// 判断当前索引是否是表单最后一项功能函数
// 函数原形:bit MenuLevelEnd (void);
// 没有参数,返回Bit标志,是最后一项返回1,不是返回0
// 调用方式:bit MenuLevelEnd (void);
//
//----------------------------------------
bit 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]; //第一行显示索引为表单第一个选项
SelectIndex = Level[sOption[SelectIndex].KeyLevel][0]; //选择索引为表单第一个选项索引
SelectLine = 1; //选择行为第一行
DIS12864M (); //刷新显示
}
else //如果不是最后的索引
{
if(SelectLine!=4) //如果当前不是屏幕最底行
{
SelectIndex++; //选择索引自加
SelectLine++; //选择行下移
SetALineReverse (SelectLine); //刷新选择行
DIS12864M (); //刷新显示
}
else //如果是屏幕最低行
{
FirstLineDisIndex++; //第一行显示下移
SelectIndex++; //选择索引自加
DIS12864M(); //刷新显示
}
}
}
//----------------------------------------
//
// 某一项功能函数 实际应该改为实际功能函数
//
//----------------------------------------
void ShutDown (void)
{
unsigned char code font[] = {"系统关闭"};
unsigned char i;
SentAIns(0x01);
SentAIns(0x92);
for(i=0;i<8;i++) SentAData(font[i]);
}
void MenuCancelOption(void);
void NoThisFunction (void)
{
unsigned char code Font[] = {"没有这个功能"};
unsigned int i,j;
SentAIns(0x01);
SentAIns(0x91);
for(i=0;i<12;i++) SentAData(Font[i]);
i = 65535;
j = 10;
do
{
do
{
i--;
}while(i);
j--;
}while(j);
MenuCancelOption();
}
void TemperatureShow(void)
{
unsigned char code Font[] = {"测试温度:"};
unsigned int i,j;
TempConvert ();
SentAIns(0x01);
SentAIns(0x90);
for(i=0;i<10;i++) SentAData(Font[i]);
for(i=0;i<6;i++) SentAData(TempFont[i]);
i = 65535;
j = 10;
do
{
do
{
i--;
}while(i);
j--;
}while(j);
MenuCancelOption();
}
//----------------------------------------
//
// 具体功能散转函数
// 函数原形:void FunctionAction
// 没有参数,没有返回值
// 调用方式:void FunctionAction (void);
//
//----------------------------------------
void FunctionAction (void)
{
switch (LastIndex) //根据进入前的索引判断具体函数
{
case 8: ShutDown(); break;
case 5: TemperatureShow(); break;
default: NoThisFunction(); break; //如果没有具体操作,显示没有这个功能
}
}
//----------------------------------------
//
// 进入某项功能函数
// 函数原形:void MenuEnterOption (void);
// 没有参数,没有返回值
// 调用方式:void MenuEnterOption (void);
//
//----------------------------------------
void MenuEnterOption (void)
{
LastIndex = SelectIndex; //标记进入前的索引号(以便判断具体功能)
SelectIndex = sOption[SelectIndex].EnterIndex; //更新选择索引为之前索引号对应进入索引
if(SelectIndex != OPTIONMETE-1) //如果当前索引不是功能选择索引
{
FirstLineDisIndex = Level[sOption[SelectIndex].KeyLevel][0]; //第一行显示为进入表单第一项
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]; //第一行显示索引为表单第一项
SelectLine = SelectIndex - Level[sOption[SelectIndex].KeyLevel][0]+1; //选择行标志为当前选择索引对应行
DIS12864M (); //刷新菜单
}
}
//----------------------------------------
//
// 菜单操作按键处理散转函数
// 函数原形:void KeyCodeAction (unsigned char KeyCode);
// 键码作为参数,没有返回值
// 调用方式:void KeyCodeAction (unsigned char KeyCode);
// 实际使用应根据自己的按键重新编写case项
//
//----------------------------------------
void KeyCodeAction (unsigned char KeyCode)
{
switch (KeyCode)
{
case 'U': MenuUpOneOption(); break; //如果是向上按键,则菜单向上,以下类似
case 'D': MenuDownOneOption(); break;
case 'E': MenuEnterOption(); break;
case 'C': MenuCancelOption(); break;
default: break;
}
}
//----------------------------------------
//
// 菜单更新函数
// 函数原形:void MenuReflash (void);
// 没有参数,没有返回值
// 调用方式:void MenuReflash (void);
// 实际应配合自己的按键编码获取程序使用
//
//----------------------------------------
void MenuReflash (void)
{
unsigned char Keytemp; //保存按键编码变量
Keytemp = GetKeyCode(); //保存按键编码
if(Keytemp) //如果按键编码有效
{
Keytemp = KeyCodeConvert (Keytemp); //根据按键编码获取按键说明字母
KeyCodeAction (Keytemp); //根据按键说明字母散转
}
}
void main (void)
{
LcdInit ();
Init18b20();
DIS12864M ();
while (1) MenuReflash ();
}