一种简单的用户界面模块

 

  在单片机项目中经常会设计一些与用户交互的程序,例如让用户通过液晶显示屏和几个按键来设置几项工作用参数.这样的程序如果组织不好会 导致浪费存储空间,添加/更改功能非常困难等问题.下面介绍一个小小的界面管理方案.希望这个程序能给您的设计带来一些启发,帮助您合理的完成设计任务.下面首先贴出界面的框架程序wnd.h和wnd.c

包含头文件wnd.h:

//wnd.h - http://www.chipart.cn

#ifndef WND_H
#define WND_H

//窗口结构
typedef struct tag_WND
{
 struct tag_WND * pParentWnd; //上级窗口
 uint8_t *Buf; //窗口专用全局空间

 void (*Load)(struct tag_WND *pWnd); //装入事件处理函数
 void (*UnLoad)(struct tag_WND *pWnd); //销毁事件处理函数
 void (*KeyEvent) (struct tag_WND *pWnd,uint8_t key); //按键处理函数
 void (*TimerEvent)(struct tag_WND *pWnd,uint8_t flag);//时钟处理函数
}WND,*PWND;

//接口函数
void CreateWnd(PWND pWnd,void (*kf)(PWND ,uint8_t) , PWND parWnd, uint8_t buf_size);
void SetCallBackWnd(PWND pWnd,void (*Load)(PWND),void (*UnLoad)(PWND),void (*TimerEvent)(PWND,uint8_t));
void SetCurrentWnd(PWND pWnd);
void ExitCurrentWnd(void);
void CurrentKeyEvent(uint8_t key);
void CurrentTimerEvent(void);

#endif

程序文件:wnd.c

/********************************
一种简单的用户界面管理模块
文件名:wnd.c
编译:WinAVR-20070525 或 VC++6.0

芯艺设计室 2004-2007 版权所有
转载请保留本注释在内的全部内容
WEB: http://www.chipart.cn
Email: changfutong@sina.com
*******************************/

//在程序中调用CreateWnd时总共为窗口分配的缓冲区大小
#define MAX_WND_BUF_SIZE 20

static PWND g_pCurrentWnd=0; //当前窗口
static uint8_t g_WndBuffer[MAX_WND_BUF_SIZE];//分配给窗口用的缓冲区
static uint8_t *g_pWndBuf=g_WndBuffer;//缓冲分配当前位置

//初始化窗口函数,参数:窗口对象指针,按键处理函数,父窗口指针,为窗口分配缓冲区大小
//对于一个窗口此函数是必须被调用的
void CreateWnd(PWND pWnd, \
void (*kf)(PWND ,uint8_t) , \
PWND parWnd, \
uint8_t buf_size)
{
 uint8_t i;

 pWnd->KeyEvent=kf; //设置按键处理函数
 pWnd->pParentWnd=(struct tag_WND *)parWnd; //设置父窗口
 pWnd->Load=0;
 pWnd->UnLoad=0;
 pWnd->TimerEvent=0;

 //分配窗口缓冲区
 pWnd->Buf=g_pWndBuf;
 g_pWndBuf+=buf_size;
 //窗口缓冲区清零
 for(i=0;i<buf_size;i++)
  pWnd->Buf[i]=0;
}

//设置窗口回调函数 ,分别设置装入时调用的Load,销毁时调用的UnLoad和窗口定时触发事件函数
//如果没有相应的函数,则指定0,此函数是可选的
void SetCallBackWnd(PWND pWnd,\
void (*Load)(PWND),\
void (*UnLoad)(PWND),\
void (*TimerEvent)(PWND,uint8_t))
{
 pWnd->Load=Load;
 pWnd->UnLoad=UnLoad;
 pWnd->TimerEvent=TimerEvent;
}

//设置当前显示窗口
void SetCurrentWnd(PWND pWnd)
{
 //如果当前窗口有销毁函数就调用
 if(g_pCurrentWnd)
 {
  if(g_pCurrentWnd->UnLoad != 0)
   g_pCurrentWnd->UnLoad(g_pCurrentWnd);
 }
 g_pCurrentWnd = pWnd;
 if(pWnd->Load != 0)
  pWnd->Load(g_pCurrentWnd);
}

//退出当前显示窗口,如果没有父窗口就不起作用
void ExitCurrentWnd(void)
{
 //如果当前窗口的父窗口有效才执行
 if(g_pCurrentWnd->pParentWnd == 0)
  return ;

 //将父窗口设置为当前窗口
 SetCurrentWnd(g_pCurrentWnd->pParentWnd);
}

//按键事件处理函数,主程序发现有按键时需调用此函数
void CurrentKeyEvent(uint8_t key)
{
 if(g_pCurrentWnd->KeyEvent != 0)
  g_pCurrentWnd->KeyEvent(g_pCurrentWnd,key);
}

//定时事件处理函数,主程序需要按一定的周期调用这个函数
void CurrentTimerEvent(void)
{
 static uint8_t flag=0;

 flag=!flag;

 if(g_pCurrentWnd->TimerEvent != 0)
  g_pCurrentWnd->TimerEvent(g_pCurrentWnd,flag);
}


   我利用这个框架写了一个设置菜单程序,这个菜单程序包含6个可调数值的选项,它用5个按键实现对各选项的编辑。这个菜单程序是display.c和display.h,这里不贴源程序了,可从 下面的下载处找到它们。

    我在三个不同的环境下实现了对这个菜单程序的调用,分别是:
        1.VC++6.0
        2.WinAVR + CA-M8X
        3.WinAVR + AvrX + CA-M8X
    下面是它们的运行结果:

界面程序在VC6.0环境下的模拟图

在CA-M8X上的测试图

 

       界面模块及演示程序下载

Copyright http://www.chipart.cn

芯艺设计室    蒙ICP备06005492号

Copyright© 2004-2010 ChipArt Design House All Rights Reserved