| 430也要GUI之一: 多级文本菜单开源 提起GUI,可能有不少朋友选择去移植UCGUI之类的东西,不过在我看来,自己写一个GUI也是一个不错的选择,功能实用就好,只要能很好的完成人机交互的任务就可以了。
 多级文本菜单是经常用到的一种功能选择方式,这里给出一个完整的实现源码,显示设备是240×320的彩色TFT液晶,改成其它分辨率的应该也很容易,输入是键盘。这个菜单程序理论上支持无限级菜单,使用的时候写一个菜单资源文件就可以了;支持用户权限控制,也就是说,可以设置不同级别的登录密码,所能看到的菜单项可以按登录级别区分;可以支持动态生成的菜单,比如说查询记录项之类。
 GUI要有良好的用户感受,基础条件是要有足够的执行速度和内存容量。不幸的是,这2点对于大多数430单片机来说都是弱项。对于149级别的MCU,用这个程序的话,建议还是用到128×128以下的单色液晶上比较好,如果用到彩色液晶上,那么滚屏显示菜单项绝对会是噩梦级的感受。如果是5x级别的,情况就好的多,240×320的彩色液晶上完全可以跑的很流畅。
 
  多级文本菜单.jpg (30.02 KB, 下载次数: 0) 下载附件 保存到相册
 多级文本菜单
 
 2015-4-6 16:07 上传 
 
 
 
 MAIN.C
 
 //===========================================================================////                                                                           //// 文件:  MAIN.C                                                            //// 说明:  BW-DK5438开发板多级文本菜单应用程序                               //// 编译:  IAR Embedded Workbench IDE for MSP430 v4.21                       //// 版本:  v1.1                                                              //// 编写:  JASON.ZHANG                                                       //// 版权:  北京拓普博维电子技术有限公司                                      ////                                                                           ////===========================================================================//#include "main.h"#pragma vector=TIMERB1_VECTOR__interrupt void TIMERB1_ISR(void){  VmainMon()                                                 ;  Event    |= SHOULD_FLICKER                                 ;  TBCTL    &= ~TBIFG                                         ;}#pragma vector=RTC_VECTOR__interrupt void RTC_ISR(void){  RTCCTL01  &=~(RTCRDYIFG + RTCTEVIFG)                       ;  Event  |= SHOULD_DISPLAY_TIME                              ;}void main(void){  WDTCTL = WDTPW+WDTHOLD                                     ;  Init_Func()                                                ;  Init()                                                     ;  MAIN_POWER_ON                                              ;  for(;;)  {    LCD_Init()                                               ;    Clear_LCD(Color_BK)                                      ;    _EINT()                                                  ;    RunMenu()                                                ;  }}//=====================================================================////                                                                     ////函数:void RunMenu(void)                                             ////描述:执行菜单调度                                                   ////                                                                     ////=====================================================================//void RunMenu(void){  unsigned char key = 0xFF , menu_index  , SubMenuIndex                   ;  unsigned char First_Item , Active_Item , Active_Item_Index              ;  unsigned char CallBackIndex                                             ;  Clear_LCD(STATUS_BK_COLOR)                                              ;  Color_BK = STATUS_BK_COLOR                                              ;  PutStringCN24(10,294,"确认")                                            ; // 底栏  PutStringCN24(185,294,"取消")                                           ;  LoadMenu(MENU_MAIN,PERMISSION)                                          ;  Initial_Menu()                                                          ;  DisplayTime()                                                           ;  for(;;)  {    key = GetKeyPress()                                                   ;    switch(key)    {    case Up: case Down: case Left: case Right:      MenuMessage(key)                                                    ;      break                                                               ;    case  8:      MenuMessage(Up)                                                     ;      break                                                               ;    case  0:      MenuMessage(Down)                                                   ;      break                                                               ;    case Esc:      {        menu_index = GetMenuIndex()                                       ;        if(Menus[menu_index].MasterMenu!=EMPTY)        {          LoadMenu(Menus[menu_index].MasterMenu,PERMISSION)               ;          Initial_Menu()                                                  ;        }        break                                                             ;      }    case OK: case Enter:      {        First_Item          = GetFirstItem()                              ;        Active_Item         = GetActiveItem()                             ;        Active_Item_Index   = GetActiveItemIndex()                        ;        if(MENU_ITEM[Active_Item_Index].CallBackFuncIndex!=EMPTY)           // 有操作函数        {          CallBackIndex= MENU_ITEM[Active_Item_Index].CallBackFuncIndex   ;          SubMenuIndex = MENU_ITEM[Active_Item_Index].SubMenuIndex        ;          if(SubMenuIndex!=EMPTY)                                           // 有操作函数且有动态子菜单          {            SubMenuIndex = MENU_ITEM[Active_Item_Index].SubMenuIndex      ;            if(Item_OP[CallBackIndex](0,Active_Item_Index  )==0x00)         // 生成子菜单成功              Initial_Menu()                                              ; // 初始化动态子菜单            else              Redraw_Menu(First_Item,Active_Item)                         ; // 未生成子菜单,重画原菜单          }          else          {            Item_OP[CallBackIndex](0,Active_Item_Index  )                 ; // 无动态子菜单            Redraw_Menu(First_Item,Active_Item)                           ; // 重画菜单          }        }        else        if(MENU_ITEM[Active_Item_Index].SubMenuIndex!=EMPTY)        {          LoadMenu(MENU_ITEM[Active_Item_Index].SubMenuIndex,PERMISSION)  ;          Initial_Menu()                                                  ;        }        break                                                             ;      }    case Power:      return                                                              ;    default:      break                                                               ;    }  }}//=====================================================================////                                                                     ////函数:Show_Help(NC1,NC2)                                             ////描述:显示帮助信息                                                   ////                                                                     ////=====================================================================//unsigned char Show_Help(unsigned int NC1,unsigned char NC2){  unsigned char key                                          ;  DrawRectFill(0,60,240,230,WINDOW_BK_COLOR)                 ;  DrawRectFill(0,30 ,240,30 ,WINDOW_COLOR)                   ;  Color    = TITLE_COLOR                                     ;  Color_BK = TITLE_BK_COLOR                                  ;  PutStringCN24(70,33,"帮助信息")                            ;  DrawRectFill(0,290,240,30,STATUS_BK_COLOR)                 ;  Color    = STATUS_COLOR                                    ;  Color_BK = STATUS_BK_COLOR                                 ;  PutStringCN24(185,294,"返回")                              ;  Color    = WINDOW_COLOR                                    ;  Color_BK = WINDOW_BK_COLOR                                 ;  DrawRectFill(0,60,240,230,WINDOW_BK_COLOR)                 ;  PutString24M(10,70 ,"↑键:[8]")                           ;  PutString24M(10,100,"↓键:[0]")                           ;  PutString24M(10,130,"菜单选择:[Enter]")                   ;  PutString24M(10,160,"菜单返回:[Cancel]")                  ;  PutString24M(10,190,"上 一 页:[←]")                      ;  PutString24M(10,220,"下 一 页:[→]")                      ;  PutString24M(10,250,"输入法切换:")                     ;  for(;;)  {    key  = ReadKey()                                         ;    if(key==Esc)   break                                     ;  }  DrawRectFill(0,290,240,30,STATUS_BK_COLOR)                 ;  Color_BK = STATUS_BK_COLOR                                 ;  Color    = STATUS_COLOR                                    ;  PutStringCN24(10,294,"确认")                               ; // 底栏  Color    = WINDOW_COLOR                                    ;  Color_BK = WINDOW_BK_COLOR                                 ;  return 0x00                                                ;}//=====================================================================////                                                                     ////函数:Set_Time(NC1,NC2)                                              ////说明:演示函数,显示时间设置成功                                     ////                                                                     ////=====================================================================//unsigned char Set_Time(unsigned int NC1,unsigned char NC2){  DrawRectFill(0,60,240,230,WINDOW_BK_COLOR)                 ;  DrawRectFill(0,30 ,240,30 ,WINDOW_COLOR)                   ;  Color    = TITLE_COLOR                                     ;  Color_BK = TITLE_BK_COLOR                                  ;  PutStringCN24(70,33,"设置时间")                            ;  DrawRectFill(0,290,240,30,STATUS_BK_COLOR)                 ;  Color    = STATUS_COLOR                                    ;  Color_BK = STATUS_BK_COLOR                                 ;  PutStringCN24(185,294,"返回")                              ;  Color    = WINDOW_COLOR                                    ;  Color_BK = WINDOW_BK_COLOR                                 ;  DrawRectFill(0,60,240,230,WINDOW_BK_COLOR)                 ;  MessageBox("信息提示","时间已设置成功")                    ;  return 0x00                                                ;}//=====================================================================////                                                                     ////函数:Set_Backlight(NC1,NC2)                                         ////说明:演示函数,显示背光已设置                                       ////                                                                     ////=====================================================================//unsigned char Set_Backlight(unsigned int NC1,unsigned char NC2){  DrawRectFill(0,60,240,230,WINDOW_BK_COLOR)                 ;  DrawRectFill(0,30 ,240,30 ,WINDOW_COLOR)                   ;  Color    = TITLE_COLOR                                     ;  Color_BK = TITLE_BK_COLOR                                  ;  PutStringCN24(70,33,"设置背光")                            ;  DrawRectFill(0,290,240,30,STATUS_BK_COLOR)                 ;  Color    = STATUS_COLOR                                    ;  Color_BK = STATUS_BK_COLOR                                 ;  PutStringCN24(185,294,"返回")                              ;  Color    = WINDOW_COLOR                                    ;  Color_BK = WINDOW_BK_COLOR                                 ;  DrawRectFill(0,60,240,230,WINDOW_BK_COLOR)                 ;  MessageBox("信息提示","背光已设置成功")                    ;  return 0x00                                                ;}//=====================================================================////                                                                     ////函数:View_Board_Info(NC1,NC2)                                       ////描述:显示帮助信息                                                   ////                                                                     ////=====================================================================//unsigned char View_Board_Info(unsigned int NC1,unsigned char NC2){  DrawRectFill(0,60,240,230,WINDOW_BK_COLOR)                 ;  DrawRectFill(0,30 ,240,30 ,WINDOW_COLOR)                   ;  Color    = TITLE_COLOR                                     ;  Color_BK = TITLE_BK_COLOR                                  ;  PutStringCN24(70,33,"开发板信息")                          ;  DrawRectFill(0,290,240,30,STATUS_BK_COLOR)                 ;  Color    = STATUS_COLOR                                    ;  Color_BK = STATUS_BK_COLOR                                 ;  PutStringCN24(185,294,"返回")                              ;  Color    = WINDOW_COLOR                                    ;  Color_BK = WINDOW_BK_COLOR                                 ;  DrawRectFill(0,60,240,230,WINDOW_BK_COLOR)                 ;  MessageBox("信息提示","BW_DK5438")                         ;  return 0x00                                                ;}//=====================================================================////函数:void VmainMon(void) —主电池电压检测                           ////=====================================================================//void VmainMon(void){  static unsigned char i = 0                              ;  static float Vmain = 0                                  ;  ADC12CTL0 |= ADC12SC                                    ;  while (!(ADC12IFG & BIT0))                              ;  Vmain     += ADC12MEM0*7.5/4095-0.4                     ;  if(++i==10)  {    Vmain   /= 10                                         ;    VmainAvr = Vmain                                      ;    Vmain    = 0                                          ;    i        = 0                                          ;  }}//=====================================================================////函数:void VmainMon(void) —显示主电源电量                           ////=====================================================================//void DrawBattery(float voltage){  DrawRectFill(213,8,24,12,STATUS_BK_COLOR)              ;  DrawRect(213,11,3,6,Green)                             ;  DrawRect(215,8,20,12,Green)                            ;  if(voltage>3.2)    DrawRectFill(217,10,4,9,Green)                       ;  if(voltage>3.0)    DrawRectFill(223,10,4,9,Green)                       ;  if(voltage>2.8)    DrawRectFill(229,10,4,9,Green)                       ;}//=====================================================================////函数:void ReadKey(void) —读取按键                                  ////=====================================================================//unsigned char ReadKey(void){  unsigned char column,row,key                   ;  unsigned char  Key                             ;  ROW_IN_COL_OUT                                 ;  row = KEY_PORT_IN&(KPR0+KPR1+KPR2+KPR3)        ;  if(row!=(KPR0+KPR1+KPR2+KPR3))  {    CLO_IN_ROW_OUT                               ;    column  = KEY_PORT_IN&(KPC0+KPC1+KPC2+KPC3)  ;    ROW_IN_COL_OUT                               ;    Key     = row + column                       ;    _NOP();    switch(Key)    {    case 0x7E:      key   = Enter                              ;      break                                      ;    case 0x7D:      key   = Cancel                             ;      break                                      ;    case 0x02FE:      key   = Up                                 ;      break                                      ;    case 0x02FD:      key   = Down                               ;      break                                      ;    case 0xEE:      key   = Left                               ;      break                                      ;    case 0xBE:      key   = Right                              ;      break                                      ;    case 0x7B:      key   = F1                                 ;      key   = Delete                             ;      break                                      ;    case 0x77:      key   = F3                                 ;      key   = Backspace                          ;      break                                      ;    case 0xE7:      key   =  1                                 ;      break                                      ;    case 0xD7:      key   =  2                                 ;      break                                      ;    case 0xB7:      key   =  3                                 ;      break                                      ;    case 0xEB:      key   =  4                                 ;      break                                      ;    case 0xDB:      key   =  5                                 ;      break                                      ;    case 0xBB:      key   =  6                                 ;      break                                      ;    case 0xED:      key   =  7                                 ;      break                                      ;    case 0xDD:      key   =  8                                 ;      break                                      ;    case 0xBD:      key   =  9                                 ;      break                                      ;    case 0xDE:      key   =  0                                 ;      break                                      ;    default:      key   =  0xFF                              ;    }  }  else    key            =  0xFF                       ;  KEY_PORT_DIR     =  0xFF                       ;  KEY_PORT_OUT     =  0x00                       ;  return key                                     ;}unsigned char GetKeyPress(void){  unsigned char Key                       ;  static unsigned long power_time = 0     ;  for(;;)  {    Key   = ReadKey()                     ;    if(Key==Power)    {      if(++power_time>300000)        return Key                        ;      else        continue                          ;    }    else      power_time  = 0x00                  ;    if(Key==0xFF)    {      __delay_cycles(560000)              ;      Key   = ReadKey()                   ;      if(Key==0xFF)     break             ;    }  }  Interval  = 0                           ;  for(;;)  {    if(Event&SHOULD_FLICKER)    {      Event  &=~SHOULD_FLICKER            ;      DrawBattery(VmainAvr)               ;    }    if(Event&SHOULD_DISPLAY_TIME)    {      Event  &=~SHOULD_DISPLAY_TIME       ;      DisplayTime()                       ;    }    Key = ReadKey()                       ;    if(Interval++>MAX_INTERVAL)      Interval   =MAX_INTERVAL            ;    if(Key!=0xFF)    {       __delay_cycles(560000)             ;      if(Key==ReadKey())      {        return Key                        ;      }    }  }}void DisplayTime(void){  unsigned char Hour,Minute                       ;  unsigned int color_temp,bkcolor_temp            ;  char string[6]                                  ;  Minute = RTCMIN                                 ;  Hour   = RTCHOUR                                ;  DrawRectFill(160,0,50,29,STATUS_BK_COLOR)       ;  sprintf(string,"%02d:%02d",Hour,Minute)         ;  color_temp   = Color                            ;  bkcolor_temp = Color_BK                         ;  Color        = STATUS_COLOR                     ;  Color_BK     = STATUS_BK_COLOR                  ;  PutStringEN16(160,8,(unsigned char *)string)    ;  Color        = color_temp                       ;  Color_BK     = bkcolor_temp                     ;}//=====================================================================////函数:void Init_Func(void)                                           ////描述:初始化函数列表                                                 ////=====================================================================//void Init_Func(void){  Item_OP[FUNC_SHOW_HELP]      = Show_Help        ; // 帮助信息  Item_OP[FUNC_BOARD_INFO]     = View_Board_Info  ; // 开发板信息  Item_OP[FUNC_SET_TIME]       = Set_Time         ; // 设置时间  Item_OP[FUNC_SET_BACKLIGHT]  = Set_Backlight    ; // 设置背光}//=====================================================================////函数:void MessageBox(char *title,char *string)                      ////功能:显示消息框                                                     ////参数: title  —消息框标题                                            ////      string —消息框内容                                            ////=====================================================================//void MessageBox(char *title,char *string){  unsigned char key                               ;  _DINT()                                         ;  Color    = TITLE_COLOR                          ;  Color_BK = TITLE_BK_COLOR                       ;  DrawRectFill(20,115,200,30,TITLE_BK_COLOR)      ;  PutStringCN24(120-strlen(title)*6,118,                (unsigned char *)title  )         ;  DrawRectFill(20,145,200,80,WINDOW_BK_COLOR)     ;  DrawRectFill(20,145,200,80,0xFFFF)              ;  DrawRect(20,145,200,80,WINDOW_COLOR)            ;  Color    = WINDOW_COLOR                         ;  Color_BK = 0xFFFF                               ;  PutString24M(120-strlen(string)*6,173,               (unsigned char *)string  )         ;  Color_BK = WINDOW_BK_COLOR                      ;  _EINT()                                         ;  for(;;)  {    key  =  GetKeyPress()                         ;    if(key==Enter||key==Esc||key==OK)      break                                       ;  }}
 复制代码
 
 
 main.h
 
 #include "msp430x54x.h"#include <stdlib.h>#include <stdio.h>#include <string.h>#include "Menu.h"#include "MenuRes.h"//#include "Edit.h"#include "TFTDRV430.H"#include "PIN_DEF.H"#include "RTC.H"#define    MAX_INTERVAL          150000#define    PERMISSION              0x03 // 菜单权限#define    RETURN_MASTER           0x33 // 函数执行完回到主菜单#define    GOTO_SUB                0x44 // 函数执行完执行子菜单/////////////////////////////////////////////////////////////////////////////////////////////////////////////#define Power  BIT0#define    VALID                   0x11#define    INVALID                 0x22//------------------------------- 事件类型定义----------------------------------//#define    SHOULD_DISPLAY_TIME     BIT0  // 应更新时间显示#define    SHOULD_FLICKER          BIT1  // 应闪烁光标#define    RX_FRAME_RECEIVED       BIT2  // 收到有效数据帧#define    TX_FRAME_WAITING        BIT3  // 串口数据等待发送#define    LOWPOWER_DETECTED       BIT5  // 电池容量低#define    SHOULD_UPDATE_WDT       BIT6  // 更新看门狗定时器#define    RX_PC_RECEIVED          BIT7  // 上位机接收到数据#define    CARD_DETECTED           BIT8  // 检测到射频卡#define    PRE_EDIT                0xFE  // 切换至上一Edit控件#define    NEXT_EDIT               0xFD  // 切换至下一Edit控件#define    INP_DIG                 BIT0  // 输入模式 —数字#define    INP_EN                  BIT1  // 输入模式 —英文字母#define    INP_CN                  BIT2  // 输入模式 —汉字///////////////////////////////////////////////////////////////////////////////////////////////////////////unsigned int OP_MODE                           ; // 操作模式-系统员级/管理员级/操作员级MENU Menu                                      ;unsigned int  Event                                    ;unsigned char INP_MODE         = INP_CN                ; // 输入模式unsigned char INP_MODE_LMT     = INP_CN+INP_EN+INP_DIG ; // 输入模式限制unsigned long int Interval     = 0xFFFFFFFF            ; // 输入键间隔float    VmainAvr              = 0                     ;unsigned int Color,Color_BK                            ;unsigned char (*Item_OP[ALL_ITEMS])(unsigned int,unsigned char)               ;unsigned char View_Board_Info(unsigned int NC1,unsigned char NC2)             ;unsigned char Set_Time(unsigned int NC1,unsigned char NC2)                    ;unsigned char Set_Backlight(unsigned int NC1,unsigned char NC2)               ;void Init_Func(void)                                                          ;void Wait_Key(unsigned char key_waited)                                       ;void Display_Time(void)                                                       ;void VmainMon(void)                                                           ;extern void Init_MCLK(void)                                                   ;extern void Init_KeyPad(void)                                                 ;extern void Init_RTC(void)                                                    ;extern void Init_timer(void)                                                  ;extern void Init_Port(void)                                                   ;extern void Init_ADC(void)                                                    ;extern void BackLight(void)                                                   ;extern void Init_UART(void)                                                   ;extern void Init_UART_115200(void)                                            ;extern void Init(void)                                                        ;extern void str_cpy(char* Destination,char* Source,unsigned char Num)         ;//////////////////////////////////////////////////////////////////////////////////////////////////////extern void Init_SPI(void)                                                     ;void RunMenu(void)                                                             ;unsigned char ReadKey(void)                                                    ;unsigned char Input_CN(char first_key,char* buffer)                            ;unsigned char GetKeyPress(void)                                                ;void DrawBattery(float voltage)                                                ;void DisplayTime(void)                                                         ;unsigned char Read_Edit_Val(unsigned char Edit_Index,char* string,                            unsigned char Renew_Edit_Index        )            ;unsigned char Valve_Mantain_Open(unsigned int NC1,unsigned char NC2)           ;void MessageBox(char *title,char *string)
 
 
 |