Chinaunix首页 | 论坛 | 博客
  • 博客访问: 628955
  • 博文数量: 112
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 1406
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-25 18:46
文章分类
文章存档

2011年(1)

2010年(5)

2009年(25)

2008年(81)

我的朋友

分类:

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   SentAData(sOption[FirstLineDisIndex].KeyWord[i]);
  if(--LineMete == 0) break;
  SentAIns(0x90);


  for(i=0;i   SentAData(sOption[FirstLineDisIndex+1].KeyWord[i]);
  if(--LineMete == 0) break;
  SentAIns(0x88);


  for(i=0;i   SentAData(sOption[FirstLineDisIndex+2].KeyWord[i]);
  if(--LineMete == 0) break;
  SentAIns(0x98);


  for(i=0;i   SentAData(sOption[FirstLineDisIndex+3].KeyWord[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 ();
}

阅读(1693) | 评论(0) | 转发(0) |
0

上一篇:常用的网站

下一篇:STM32的IAP下载与设置

给主人留下些什么吧!~~