交互界面设计(草稿)

方案一:简单按键扫描

  硬件:独立按键,液晶;

  软件架构:

全局变量;
外设(如DA)输出初始化;
液晶初始化显示;
while(1)
{
按键扫描();
}

  液晶需要显示的内容数值和外设的数值放在全局变量里面。在按键扫描程序中检测独立按键是否拉低,若拉低进行去抖动延时再检测,根据相应的按键值改变全局变量并更新液晶显示和外设输出。

方案二:菜单

LCD12864_Menu.c代码如下。提示:代码中包含扫描式矩阵按键头文件和LCD12864显示头文件。本想将数据和函数分离开,写成.c加.h形式,但因此代码数据和函数混在一起,故写在一个.c文件中。

基本概念:1、菜单分层次。主菜单是第1层,为最顶层。子菜单若无子节点,则为最底层菜单。主菜单无父节点。

       2、每一层次菜单菜单项称作数据节点。下列代码中每个数据节点包含信息有:当前层菜单节点总数、节点标题,节点函数,子节点(下一层菜单指针),父节点(上一层菜单指针)。

     3、程序运行中,菜单更新函数依照按键值执行相应功能。若节点函数存在,则执行函数,等待按键返回菜单显示界面;若节点函数不存在则更新菜单显示。

//=================================版本信息==================================//

//Ver:2011082601

//Author:XZQ

//===========================================================================//

//=================================头文件=============================//

#include "msp430f5438.h"

#include "MCU_Init.h"

#include "LCD12864_Driver.h"

#include "ArrayKey_Driver.h"



#define Null 0

/********************** 

* 菜单结构体定义 * 

**********************/ 

struct MenuItem

{ 

	unsigned char MenuCount;  //当前层节点数

	unsigned char *DisplayString; //节点标题

	void (*Subs)();  //节点函数

	struct MenuItem *ChildrenMenus; //子节点

	struct MenuItem *ParentMenus; //父节点

}; 

//=================================菜单变量定义=============================//

/*********************** 

* 全局变量声明区 * 

***********************/ 

unsigned char DisplayStart = 0; //显示时的第一个菜单项

unsigned char UserChoose = 0;  //用户所选菜单项

unsigned char DisplayPoint = 0;//显示指针

unsigned MaxItems;  //同层所有节点数

unsigned char ShowCount=4; //单屏显示最多节点数

unsigned char Menu_key=0;//菜单函数中存放按键值变量

void DispVoid(void)

{

  DispOneChar(0,0,0x30);

}

void NullSubs(void) //空操作函数

{ 

}

//菜单变量声明

struct MenuItem Vol_Menu[3];

struct MenuItem FFT_Menu[3];

struct MenuItem Fre_Set_Menu[3];

struct MenuItem Fre_Test_Menu[4];

struct MenuItem MainMenu[6];

struct MenuItem (*MenuPoint) = MainMenu; //结构体指针,初始化时指向主菜单

//********************第2层菜单变量******************************//

struct MenuItem FFT_Menu[3]=

{ //MenuCount  DisplayString  Subs  ChildrenMenus ParentMenus

{3,  "  【频谱显示】" , NullSubs,  Null,  MainMenu},

{3,  "1.频率测量    ",  DispVoid,  Null,  MainMenu},

{3,  "2.返回",  NullSubs,  MainMenu,  MainMenu}, 

};



struct MenuItem Vol_Menu[3]=

{ //MenuCount  DisplayString  Subs  ChildrenMenus ParentMenus

{3,  "  【幅值测量】 " , NullSubs,  Null,  MainMenu},

{3,  "1.频率测量    ",  NullSubs,  Null,  MainMenu},

 {3, "2.返回",  NullSubs,  MainMenu,  MainMenu},

};



struct MenuItem Fre_Set_Menu[3]=

{ //MenuCount  DisplayString  Subs  ChildrenMenus ParentMenus

{3,  "  【频率设置】 " , NullSubs,  Null,  MainMenu},

{3,  "1.频率设置    ", Clear_GDRAM ,  Null,  MainMenu},

{3,  "2.Back",  NullSubs,  MainMenu,  MainMenu}, 

};



struct MenuItem Fre_Test_Menu[4]=

{ //MenuCount  DisplayString  Subs  ChildrenMenus ParentMenus

{4,  "  【测频、测相】" , NullSubs,  Null,  MainMenu},

{4,  "1.频率测量    ",  NullSubs,  Null,  MainMenu},

{4,  "2.相位测量    ",  NullSubs,  Null,  MainMenu},

{4,  "3.返回",  NullSubs,  MainMenu,  MainMenu},	 

};

//********************第1层菜单变量:主菜单******************************//

struct MenuItem MainMenu[6]=

{//MenuCount DisplayString Subs     ChildrenMenus ParentMenus

{6,  "  【主菜单】   " , NullSubs,  Null,         Null},

{6,  "1.测频、测相  "  , NullSubs,  Fre_Test_Menu,Null},

{6,  "2.频率设置"      , NullSubs,  Fre_Set_Menu, Null},

{6,  "3.幅值测量"      , NullSubs,  Vol_Menu,     Null},

{6,  "4.频谱显示"      , NullSubs,  FFT_Menu,     Null},

{6,  "5.返回"          , NullSubs,  MainMenu,     MainMenu},

}; 

//=================================菜单函数定义=============================//

//菜单界面初始化显示

void ShowMenu(void) 

{

	unsigned char n;

	MaxItems = MenuPoint[0].MenuCount;//得到主层菜单节点个数

	DisplayPoint = DisplayStart;//指向该层菜单第一个节点

	for(n=0;(DisplayPoint<MaxItems)&&(n<ShowCount);n++) 

	{	 	 			   

		DispStr(0,n,MenuPoint[DisplayPoint++].DisplayString);

	}	

}

//菜单界面显示更新

void Menu_Change(uchar KeyValue)

{

    switch(KeyValue) //根据按键值选择相应操作

    {  

		case UP: 

				UserChoose --; 

				if (UserChoose ==255)

				{ 

					UserChoose = 0;//上翻截至,如果要回滚赋值MaxItems-1

				} 

				break; 

                case Down: 

				UserChoose ++; 

				if (UserChoose == MaxItems ) 

				{ 

					UserChoose = MaxItems-2;//下翻截至,如要回滚赋值为0 

				} 

				break; 

		case Esc: 

				if (MenuPoint[UserChoose].ParentMenus != Null) 

				{ 

					MenuPoint = MenuPoint[UserChoose].ParentMenus; 

					UserChoose = 0; 

					DisplayStart = 0; 

				} 

				break; 

		case Enter: 

				if (MenuPoint[UserChoose].Subs != NullSubs) //如果函数不为空,说明是底层菜单,执行函数

				{ 

					Clear_DDRAM(); 

	  	                        (*MenuPoint[UserChoose].Subs)(); 

                                        Menu_key=KeyDefault;//改变Menu_key,确保一次按键只执行一次代码

					while(Menu_key!=Esc)

                                          Menu_key=KeyScan();

				} 

				else if (MenuPoint[UserChoose].ChildrenMenus != Null)//函数为空,子层不为空,不是底层菜单,设置下一菜单显示数据 

				{ 

					MenuPoint = MenuPoint[UserChoose].ChildrenMenus; 

					UserChoose = 0; 

					DisplayStart = 0; 

				} 

				break; 

		

		default:break;

	}

		//KEY_FLAG = 0;

	 	Clear_DDRAM(); 

	  	//delay_ms(10);  //液晶为慢速器件

		

		

		if ((UserChoose%ShowCount==0) && (KeyValue == Down))  //一屏只能显示ShowCount行

		{	

			DisplayStart = UserChoose;	  // UserChoose = 4; 

		}

		if (((UserChoose)%(ShowCount-1)==0) && (KeyValue == UP))  //一屏只能显示ShowCount行

		{	

			DisplayStart = 0;

		}

 

		ShowMenu();//显示更新后的菜单

		if(UserChoose == 0)

			UserChoose = 1 ;

		//if(UserChoose != 0)

			DispStr(14,UserChoose%ShowCount,"←");	

} 

你可能感兴趣的:(界面设计)