amobbs.com 阿莫电子技术论坛

标题: 发一个裸机下的界面编写方式.,,不用结构体,,设计简单,思路清晰,没有死循环,,,,使用 [打印本页]

作者: xpstudio2003    时间: 2009-12-10 11:02
标题: 发一个裸机下的界面编写方式.,,不用结构体,,设计简单,思路清晰,没有死循环,,,,使用
发一个代码.也是本人在长期的写程序中慢慢摸索出来的,不敢说是独创..也算是原创.呵呵,,

这个代码编译不通过,,因为我只把最重要的两个文件从工程中拿了出来,,其它的就不用了,,

大体说明一下.

每个界面有一个函数.
每个界面有一个初始化函数.


每个界面有一个标记STS


点击此处下载 ourdev_512719.rar(文件大小:2K) (原文件名:code.rar)


....

不多说了,,
个人在多个项目中使用过,稳定性很好.
没有使用那些乱七八糟的定时器,中断之类的东西,,,
作者: AL_DWF    时间: 2009-12-10 11:26
这方法确实思路清晰,但程序大时候,占用程序空间相对较大,很多的switch
曾经用过.深有感触
作者: xpstudio2003    时间: 2009-12-10 12:18
是啊,,一个界面一个SWITCH,

反过来想,,
无论用什么方法写,都是在一个界面里来操作按键,怎么着也得去做按键的对应处理,,,
作者: eduhf_123    时间: 2009-12-10 12:53
MARK GUI
作者: Gorgon_Meducer    时间: 2009-12-10 13:12
呵呵……恭喜LZ也摸索出这种模式了哈。这种工程模式我已经用很久了!不过我不使用switch,因为
局限性很大,每个状态机通常只能有一条执行线路。我使用if结构,这样每个状态机可以有多个并发
的执行线路。我注意到,你的代码中还没有使用调度器。其实配合这种状态机系统,可以用很简单的
合作式调度器来控制状态机的启动状态。有兴趣可以参考我的一些代码。
同时,配合这种编程方式,我正在酝酿一种可视化集成开发环境。哎……可惜一直没有时间实施……
作者: AL_DWF    时间: 2009-12-10 13:26
【4楼】 Gorgon Meducer 傻孩子
"我注意到,你的代码中还没有使用调度器。其实配合这种状态机系统,可以用很简单的
合作式调度器来控制状态机的启动状态。有兴趣可以参考我的一些代码。
"

Gorgon Meducer 傻孩子
您曾写的哪个代码有用到过这种方式的?很想学习下.
作者: astudent    时间: 2009-12-10 13:28
4楼,能否发一个按LZ所说方式、基于合作式调度器的例子?
作者: cgbabc    时间: 2009-12-10 13:34
顶一个
作者: astudent    时间: 2009-12-10 14:16
好贴,再顶顶!
作者: jim166783    时间: 2009-12-10 14:33
以下是我的裸机界面,可以参考下

void (*Thrd)(void);
char InitFlag=1;

//时间设置
void TimeSet(void)
{
        if(InitFlag == 1)//需要初始化界面
        {

                InitFlag=0;
        }
        if(Key == KEY_NONE)return ;
        switch(Key)
        {
                case KEY_EXIT:
                        Thrd = ProcMainKey;//返回主界面
                        InitFlag = 1;//并需要刷新界面
                        break;

                default:
                        break;

        }
}

//日期设置
void DateSet(void)
{
        if(InitFlag == 1)//需要初始化界面
        {

                InitFlag=0;
        }
        if(Key == KEY_NONE)return ;
        switch(Key)
        {
                case KEY_EXIT:
                        Thrd = ProcMainKey;//返回主界面
                        InitFlag = 1;//并需要刷新界面
                        break;

                default:
                        break;

        }
}

//按键提示设置
void KeyToneSet(void)
{
        if(InitFlag == 1)//需要初始化界面
        {

                InitFlag=0;
        }
        if(Key == KEY_NONE)return ;
        switch(Key)
        {
                case KEY_EXIT:
                        Thrd = ProcMainKey;//返回主界面
                        InitFlag = 1;//并需要刷新界面
                        break;

                default:
                        break;

        }
}

void ProcMainKey(void)
{
        if(InitFlag == 1)//需要初始化界面
        {

                InitFlag=0;
        }
        if(Key == KEY_NONE)return ;
        switch(Key)
        {
                KEY1:
                        Thrd = TimeSet;//将“TimeSet”扔到while(1)里面循环
                        InitFlag = 1;
                        break;
               
                KEY2:
                        Thrd = DateSet;//将“DateSet”扔到while(1)里面循环
                        InitFlag = 1;
                        break;
               
                KEY3:
                        Thrd = KeyToneSet;//将“KeyToneSet”扔到while(1)里面循环
                        InitFlag = 1;
                        break;
               
                default:
                        break;
        }
}

void main(void)
{
        Thrd = ProcMainKey;
        while(1)
    {
        Thrd();
    }           

}
作者: gwh1128    时间: 2009-12-10 17:46
标记下,会火
作者: plc_avr    时间: 2009-12-10 18:19
MARK一下,谢谢。
作者: lv998127    时间: 2009-12-10 18:34
排队学习
作者: eddia2000    时间: 2009-12-10 18:58
[Gorgon Meducer 傻孩子]:
    请把你的代码上传来看下,谢谢!
作者: shanyan    时间: 2009-12-10 19:35
MARK
作者: 2nd090215    时间: 2009-12-10 19:57
关注下
作者: kdtcf    时间: 2009-12-10 20:00
很好,顶
作者: jchqxl    时间: 2009-12-10 20:22
Gorgon Meducer 傻孩子

可否把您的相关代码贴上来学习一下,谢谢。
作者: taishandadi    时间: 2009-12-10 20:51
不错,学习经验。
作者: cjr82123    时间: 2009-12-10 20:55
值得参考啊,谢谢!
作者: song1km    时间: 2009-12-10 21:05
真正有价值的怎能不标。。。。。个。。记。
作者: astudent    时间: 2009-12-10 21:32
傻孩子,都在等你!
作者: liuweiele    时间: 2009-12-10 21:36
灵活运用C语言的 结构体 和 指针,可以达到 事半功倍 的效果~
作者: zjr0411    时间: 2009-12-10 22:50
记号
作者: Bird    时间: 2009-12-10 23:12
顶一个
作者: Si_Bin    时间: 2009-12-10 23:21
偶用函数指针表....
作者: shipingjing    时间: 2009-12-10 23:22
记号
作者: fuanzwg    时间: 2009-12-10 23:29
mark
作者: zhangjw    时间: 2009-12-10 23:32
mark,等傻孩子
作者: STM32_Study    时间: 2009-12-11 00:15
等傻孩子的方案
作者: Gorgon_Meducer    时间: 2009-12-11 09:57
我这里有两个调度器,一个是过去用的简单版本,一个是后来的改进版本,但是原理都基本一样。
这里我只说一下原理:
所有的C函数都可以看作是状态机,哪怕是一个最简单的函数,也可以看成是一个只有一个状态的
状态机。因此,最简单的状态机原型可以是大家常用的:
void FSMExample(void);

为了方便控制状态机的启动和关闭,我修改了最基本的原型:
BOOL FSMExample(void);

这就是最简单的双态状态机:
当函数返回TRUE,表明该状态机仍然“希望”处于运行状态;
当函数返回FALSE,表明该状态机已经完成,希望终止。

根据这一规定,如果通过函数指针把所有的状态机连接起来,就可以形成下面的简单调度器:
typedef struct Process
{
    BOOL (*Proc)(void);                                 //返回False,自动关闭任务
    volatile BOOL IfProcAlive;
}PROCESS;

typedef BOOL (*PROC_FUNCTION)(void);

void Process_Task(void)
{
    static uint8 n = 0;
   
    if (ProcPCB[n].IfProcAlive)                             //处理进程
    {
        ProcPCB[n].IfProcAlive = (*ProcPCB[n].Proc)();
    }        
   
    n ++;
    if (n >= g_cCOSPROCCounter)
    {
        n = 0;
        //g_cScheduleTest = MIN(g_cScheduleTest + 1,254);
    }
}

这个调度器很简单,就是检测一个注册了的顶层状态机其Alive状态是否为TRUE,
如果为TRUE,就调用;同时在调用后将状态机的返回值重新赋给ALive属性,这样
状态机就可以通过在函数中返回TRUE或者FALSE来控制自己的运行状态。

同时,利用这一特性,状态机里面也可以调用其他子状态机,只需要在某一个状态
中调用子状态机函数并检测返回值是否为FALSE就可以知道子状态机的运行情况。

下面是一个状态机内部的例子:

#define FSM_ACTION_FLAG         s_tbState.Bits
#define FSM_STOP_ALL_ACTIONS    s_tbState.Value = 0;
#define FSM_START               FSM_ACTION_FLAG.BIT0
#define FSM_STATE_A             FSM_ACTION_FLAG.BIT1
...

BOOL FSMExampleB(void)
{
    ...
}

BOOL FSMExampleA(void)
{
    static ES_BYTE s_tbState = {0};
   
    if (0 == s_tbState.Value)
    {
        FSM_START = TRUE;                      //自动开始标志……
    }

    if (FSM_START)
    {
        //一些初始化操作
        ....
        FSM_START = FALSE;
        FSM_STATE_B = TRUE;
    }

    if (FSM_STATE_B)
    {
        if (!FSMExampleB())    //调用子状态机
        {
            //子状态机完成
            ...

            FSM_STATE_B = FALSE;
            FSM_STATE_C = TRUE;   //同时激活两个状态,比如,其中一个
            FSM_STATE_D = TRUE;   //用于检测某个超时计数器
        }
    }

    if (FSM_STATE_C)
    {
        //等待某些出发条件,比如等待某一个引脚电平为低
        if (等待某个触法条件)
        {
            //条件触法了,比如监测到某个引脚电平为低了

            ...                   //一些操作

            FSM_STATE_C = FALSE;
            FSM_STATE_E = TRUE;
        }
    }

    if (FSM_STATE_D)
    {
        if (检测是否超时)
        {
            //发生了超时

            ...                            //可以设置一些标志

            FSM_STOP_ALL_ACTIONS;          //复位状态机
            return FALSE;                  //关闭状态机
        }
    }

    if (FSM_STATE_E)
    {
        //假设这个状态是一个正常的终止态

        ...

        FSM_STOP_ALL_ACTIONS;
        return FALSE;
    }

    return TRUE;
}

使用if结构的好处是,每一个子状态都可以独立被激活,也就是可以并发激活,
对于一些明显是互斥的状态,就可以用if (){}else if (){}结构来提高效率;
同时,对于一些拥有优先级的状态,也可以用 if ... else if结构来组织。

使用这种结构,实际上可以把每一个函数看成一个 进程, 而每一个内部if结构
看成一个线程。这也符合“进程含有资源”,“线程通常不含有资源”的描述。

有兴趣的人可以发现,我的很多代码都是这种结构的。
作者: astudent    时间: 2009-12-11 10:01
期待傻孩子更详细的论述!
作者: jackiezeng    时间: 2009-12-11 10:12
之前我也用这种状态机的方法来编写,,,但是我后来发现使用一些简单的时间片调度系统,更方便。
作者: Gorgon_Meducer    时间: 2009-12-11 10:13
老版本简易调度器
点击此处下载 ourdev_513080.rar(文件大小:8K) (原文件名:FSM_EASY.rar)

新版本调度器
点击此处下载 ourdev_513081.rar(文件大小:28K) (原文件名:FSM_V2.rar)
作者: hisun    时间: 2009-12-11 10:17
好东西
作者: du722    时间: 2009-12-11 16:09
mark
作者: spely    时间: 2009-12-11 18:36
顶~
作者: laolu    时间: 2009-12-11 18:45
不能不顶
作者: huike    时间: 2009-12-11 20:51
MARK
作者: hephi    时间: 2009-12-12 00:44
MARK
作者: xpstudio2003    时间: 2009-12-12 01:38
看来我这块砖扔的还行...
作者: t2397362    时间: 2009-12-12 08:09
好帖马克之
作者: ndust    时间: 2009-12-12 08:18
jh
作者: xk2yx    时间: 2009-12-12 08:27
mark
作者: shabby    时间: 2009-12-12 08:50
记号,有时间仔细看看。
作者: xpstudio2003    时间: 2009-12-13 11:03
参考了Gorgon Meducer 傻孩子的程序,,收获不小..

我自己改了下自己的界面程序写法.
去掉了状态变量标志.

没有改掉的是SWITCH这块,,虽然不如IF的效率高,但是直观一些,,也一直没想出来别的方法,直观但效率也要高的.


//////
以下程序仅讨论人机界面UI处理.

现在的方式是.
每个界面用一个函数来表示.
每个函数里就是处理按键.用的SWITCH方式.关于按键的产生,我在我另一个帖子里也贴出了程序.

用的函数指针来进行界面的切换.


定了了三个宏

#define                UI_GOTO(index)                        {pUI=(index);}
#define                UI_GOTO_CHILD(index)                {pUI=(index); KeyDir=GOTO_CHILD;}
#define                UI_GOTO_FATHER(index)                {pUI=(index); KeyDir=GOTO_FATHER;}


大家不要省砖,,,俺家要盖房子.

点击此处打开 ourdev_513809.txt(文件大小:5K) (原文件名:xpUI example.txt)


再上传我的按键处理程序
可以响应多种方式,,,KEY_DOWN KEY_HOLD KEY_BURST KEY_UP  KEY_DOUBLE
用按键属性值返回.与SWITCH组合非常方便直观



点击此处下载 ourdev_513811.txt(文件大小:1K) (原文件名:key.h.txt)
点击此处下载 ourdev_513812.txt(文件大小:6K) (原文件名:key.c.txt)
作者: dreampet    时间: 2009-12-13 11:24
不错 有空慢慢看
作者: hebj    时间: 2009-12-13 11:24
学习一下。
作者: astudent    时间: 2009-12-14 19:54
顶楼主,加盖一层楼!
作者: quzegang    时间: 2009-12-14 20:04
Mark
作者: feigoo    时间: 2009-12-14 21:13
MK
作者: voidx    时间: 2009-12-18 17:59
标记。
作者: bad_fpga    时间: 2009-12-18 19:44
mark
作者: zhujlong    时间: 2009-12-18 19:57
mark
作者: wangyi1e    时间: 2009-12-18 20:35
mark,学习一下!
作者: ddcour    时间: 2009-12-18 22:52
标记!
作者: yan_jian    时间: 2009-12-18 23:37
不错!学习了
作者: avr-arm    时间: 2009-12-19 22:28
看了半天,我没看懂状态机,我的多层界面采用索引
//定义按键功能指针
void (*KeyFuncPtr)(void);         

/*定义类型*/
typedef struct
{  unsigned int KeyStateIndex;   //当前的状态索引号
   void (*CurrentOperate)(void);      //当前状态应该执行的功能操作
}  StateTab;

/*-------------------------------------------------------------*/
StateTab KeyTab[MENU_SIZE]=
{
   {1,(*main_main)},
   {11,(*main_0)},      //参数设置
   {12,(*main_0)},      //数据监视   
   {13,(*main_0)},      //关于
   {14,(*main_14)},     //手动发送
   {15,(*main_14_set)}, //设置为自动发送
   {151,(*main_main)},  //
   {141,(*hand_send)},
   {111,(*main_11)},      //参数设置子菜单 主站号码
   {112,(*main_11)},      //温度限定           //5
   {113,(*main_11)},      //过压限定
   {114,(*main_12)},      //过流限定
   {115,(*main_12)},      //欠压限定
   {116,(*main_12)},      //功率限定
   {117,(*main_13)},      //全部默认          //10
   {118,(*main_13)},      //数据存储
   {119,(*main_13)},      //自动发送频率设定
   {131,(*about)},       //关于子菜单
   {1111,(*set_number)}, //设置主站号码
   {1121,(*main_121)},    //温度限定子         //14
   {1122,(*main_121)},    //wenduxianding      
   {11211,(*set_temph)},  //高温限定
   {11221,(*set_templ)},  //低位限定
   {1131,(*set_ovv)},    //过压限定设置
   {1141,(*set_ovi)},    //过流设置            //19
   {1151,(*set_qy)},     //欠压设置
   {1161,(*set_ovw)},    //功率限定设置
   {1171,(*set_default)},//默认设置
   {1181,(*set_store)},  //数据存储    23
   {121,(*main_21)},               //数据监视gsm
   {122,(*main_21)},               //电能
   {123,(*main_21)},               //开关量
   {124,(*main_22)},               //   温度          27
   {1221,(*main_221)},//三相电压电流
   {1222,(*main_221)},//三功率 29
   {1223,(*main_221)},//有功功率
   {1224,(*main_224)},//无功功率
   {1231,(*rd_switch)},  //开关量读取函数      31
   {1211,(*main_211)},  //gsm子--at
   {1212,(*main_211)},  //init
   {1213,(*main_211)},  // 发信息测试                   34
   {12111,(*test_at)},  //at
   {12121,(*test_init)}, //init
   {12131,(*test_sms)},  //sms
   {12211,(*axiang)},
   {12221,(*abcxiang)},     //41
   {12231,(*abcxiang2)},
   {12241,(*abcxiang3)},
   {1241,(*wendu)},  //41
   {1191,(*set_auto)},      //自动发送频率设定
};
/*-------------------------------------------------------------*/
void Menu_Change(unsigned char key)
{
unsigned char i=0;
unsigned int temp;
unsigned char cengxian[5]="";

                         //                                     第一层   第二层    第三层    第四层    第五层
//unsigned char status[]={0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x20,0x2d,0x20,0x2d,0x20,0x2d,0x20};//
unsigned char status_s[]  ="        - - - - ";
      //第一层菜单偏移为8  第二为10 第三为12  第四为14  第五为16
          if(zidongesc)
           {zidongesc=0;
           key=Esc;
           }
    switch(key)
        {
            case  UP:                       //向上的键
                {
                   temp=Menu_Index-1;
                   for(i=0;i<MENU_SIZE;i++)
                      {if(temp==KeyTab.KeyStateIndex) {Menu_Index=temp;tab_num=i;break;}
                          }
                 break;  
            }
                case Enter:                           //回车键
                {
                        temp=Menu_Index*10+1;
                   for(i=0;i<MENU_SIZE;i++)
                      {if(temp==KeyTab.KeyStateIndex) {Menu_Index=temp;tab_num=i;break;}
                          }
                        break;
                }
                case  Down:                          //向下的键
                {
                        temp=Menu_Index+1;
                   for(i=0;i<MENU_SIZE;i++)
                      {if(temp==KeyTab.KeyStateIndex) {Menu_Index=temp;tab_num=i;break;}
                          }
                        break;
                }
                case Esc:            //退出键
                {
                temp=Menu_Index/10;
                   for(i=0;i<MENU_SIZE;i++)
                      {if(temp==KeyTab.KeyStateIndex) {Menu_Index=temp;tab_num=i;break;}
                          }
                        break;
                }
        }
        KeyFuncPtr=KeyTab[tab_num].CurrentOperate;

        (*KeyFuncPtr)();     //执行当前的按键操作
        if(key)
        OSWait(K_TMO,30);
        if(key||caidanxiang)
{
        if(Menu_Index<=10) {cengxian[0]=Menu_Index;cengxian[1]=10;cengxian[2]=10;cengxian[3]=10;cengxian[4]=10;}
        if((Menu_Index>10)&&(Menu_Index<100)) {cengxian[0]=Menu_Index/10;cengxian[1]=Menu_Index%10;cengxian[2]=10;cengxian[3]=10;cengxian[4]=10;}
    if((Menu_Index>100)&&(Menu_Index<1000)) {cengxian[0]=Menu_Index/100;cengxian[1]=(Menu_Index%100)/10;cengxian[2]=Menu_Index%10;cengxian[3]=10;cengxian[4]=10;}
    if((Menu_Index>1000)&&(Menu_Index<10000)) {cengxian[0]=Menu_Index/1000;cengxian[1]=(Menu_Index%1000)/100;cengxian[2]=((Menu_Index%1000)%100)/10;cengxian[3]=Menu_Index%10;cengxian[4]=10;}
    if(Menu_Index>10000) {cengxian[0]=Menu_Index/10000;cengxian[1]=(Menu_Index%10000)/1000;cengxian[2]=((Menu_Index%10000)%1000)/100;cengxian[3]=(((Menu_Index%10000)%1000)%100)/10;cengxian[4]=Menu_Index%10;}
        status_s[7]=cengxian[0]+48;
        status_s[9]=cengxian[1]+48;
        status_s[11]=cengxian[2]+48;
        status_s[13]=cengxian[3]+48;
        status_s[15]=cengxian[4]+48;
    display_str(3,0,status_s);       
    caidanxiang=0;//实现首次进入餐单就刷新一次
if(!zhizhen)
{        switch ((Menu_Index%10)-1)
        {
        case 0:display_str(0,0,"->");display_str(1,0,"--");display_str(2,0,"--");break;
        case 1:display_str(0,0,"--");display_str(1,0,"->");display_str(2,0,"--");break;
        case 2:display_str(0,0,"--");display_str(1,0,"--");display_str(2,0,"->");break;
        case 3:display_str(0,0,"->");display_str(1,0,"--");display_str(2,0,"--");break;
        case 4:display_str(0,0,"--");display_str(1,0,"->");display_str(2,0,"--");break;
        case 5:display_str(0,0,"--");display_str(1,0,"--");display_str(2,0,"->");break;
        case 6:display_str(0,0,"->");display_str(1,0,"--");display_str(2,0,"--");break;
        case 7:display_str(0,0,"--");display_str(1,0,"->");display_str(2,0,"--");break;
        case 8:display_str(0,0,"--");display_str(1,0,"--");display_str(2,0,"->");break;
        }
}
}

}
作者: dongdaxing    时间: 2009-12-20 10:37
不错!学习了
作者: gdourf    时间: 2009-12-20 13:45
MARK
作者: bsz84    时间: 2009-12-20 13:46
学习,好好学习!
作者: erxun    时间: 2009-12-20 13:54
也贴一个界面处理的函数,
根据screen_status数值来跑 。
void get_screen_status(void)   
{  

   get_key_value();  //获取键值
/*********************运行画面响应**********************/
  if(screen_status == 0x00)
    {
          //时间显示刷新
          time_show();
          if(key_Press_flag)//有键按下
          {
                 if(key_value == Enter_key_value)  //确认按下
                 {
                           chn_disp(Menu_tab);                      //菜单 显示
                        Cursor_menu = 1;                  //菜单光标=1,
                        Highlight_Cursor_menu();//菜单光标显示
                        screen_status = 0x01;             //屏幕状态改为:菜单
                 }
                 key_value = 0;           //键盘数据清除,等下下一次的操作
                 key_Press_flag = 0;
          }
          
          asm("nop");
        }
/*********************运行响应结束*********************/

/*********************菜单画面响应**********************/
  if(screen_status == 0x01)
    {
          
          if(key_Press_flag)//有键按下
          {
             //菜单光标处理,转移到其它画面
                 Cursor_menu_TAB_show();
                 if(key_value == Back_key_value)  //返回按下
                 {
                    Highlight_Clear(); //删除所有光标
                        chn_disp(run_tab);                      //运行画面 显示
                        Cursor_menu = 1;                  //菜单光标=1,
                        screen_status = 0x00;             //屏幕状态改为:运行
                 }       
         
                 key_value = 0;           //键盘数据清除,等下下一次的操作
                 key_Press_flag = 0;
          }
        }
/*********************菜单响应结束*********************/
/*********************瞬时值画面响应**********************/
  if(screen_status == 0x02)
    {
          Now_value_View_show();
          if(key_Press_flag)//有键按下
          {
                 if(key_value == Back_key_value)  //返回按下
                 {
                        Highlight_Clear();
                        chn_disp(Menu_tab);                      //菜单画面 显示
                        Highlight_Cursor_menu();          //菜单光标显示
                        screen_status = 0x01;             //屏幕状态改为:菜单
                 }       
                 
         Cursor_now_TAB_show(); //瞬时值光标处理
                 key_value = 0;           //键盘数据清除,等下下一次的操作
                 key_Press_flag = 0;
          }
        }
/*********************瞬时值响应结束*********************/
/*********************历史值画面响应**********************/
  if(screen_status == 0x03)
    {
          History_value_View_show();
          if(key_Press_flag)//有键按下
          {
                 if(key_value == Back_key_value)  //返回按下
                 {
                         Highlight_Clear();
                        chn_disp(Menu_tab);                      //菜单画面 显示
                        Highlight_Cursor_menu();          //菜单光标显示
                        screen_status = 0x01;             //屏幕状态改为:菜单
                 }       
         Cursor_History_TAB_show();
                 key_value = 0;           //键盘数据清除,等下下一次的操作
                 key_Press_flag = 0;
          }
        }
/*********************历史值响应结束*********************/
/*********************历史值查询画面响应**********************/
  if(screen_status == 0x06)
    {
          
          if(key_Press_flag)//有键按下
          {
                 if(key_value == Back_key_value)  //返回按下
                 {
               chn_disp(History_tab);
                       Highlight_Cursor_History();
                       screen_status = 0x03;
                 }       
         
                 key_value = 0;           //键盘数据清除,等下下一次的操作
                 key_Press_flag = 0;
          }
        }
/*********************历史值查询响应结束*********************/
/*********************设置画面响应**********************/
  if(screen_status == 0x04)
    {
          time_set_show(); //参数修改 显示
          if(key_Press_flag)//有键按下
          {
                 Cursor_Set_TAB_show(); //修改光标
                 
                 if(key_value == Back_key_value)  //返回按下
                 {
                        Highlight_Clear();
                        chn_disp(Menu_tab);                      //菜单画面 显示
                        Highlight_Cursor_menu();          //菜单光标显示
                        screen_status = 0x01;             //屏幕状态改为:菜单
                 }       
                 key_value = 0;           //键盘数据清除,等下下一次的操作
                 key_Press_flag = 0;
          }
        }
/*********************设置响应结束*********************/
/*********************帮助画面响应**********************/
  if(screen_status == 0x05)
    {
          
          if(key_Press_flag)//有键按下
          {
                 if(key_value == Back_key_value)  //返回按下
                 {
                        chn_disp(Menu_tab);                      //菜单画面 显示
                        Highlight_Cursor_menu();          //菜单光标显示
                        screen_status = 0x01;             //屏幕状态改为:菜单
                 }       

                 key_value = 0;           //键盘数据清除,等下下一次的操作
                 key_Press_flag = 0;
          }
        }
/*********************帮助响应结束*********************/
}
作者: 525133174    时间: 2009-12-20 14:15
火了
mark
作者: taishandadi    时间: 2009-12-20 14:28
此贴火了。
作者: fy024    时间: 2009-12-20 16:31
mark
作者: D.lovers    时间: 2009-12-20 16:51
mark.学习
作者: wuxianglei    时间: 2009-12-21 00:25
marl
作者: hhrfjz    时间: 2009-12-21 00:35
MARK
作者: electricit    时间: 2009-12-21 07:58
程序当然得这么写喽,看网上人家写的GSM发短信程序,发一个while一下,发一个while一下,别的活还要不要干啦
SWITCH与IF各有千秋,
作者: yzlyear    时间: 2009-12-21 08:34
mark
作者: zzwuyu    时间: 2009-12-21 08:39
mark
作者: by886    时间: 2009-12-21 09:30
先mark 慢慢学习
作者: bigworms    时间: 2009-12-21 09:47
mark
作者: lhj200304    时间: 2009-12-21 15:08
慢慢看,不过跟写个结构体,然后用函数指针有多大的区别?
作者: haigerl    时间: 2009-12-21 15:28
mark
作者: avrpicarm    时间: 2009-12-21 16:32
越简单越灵活,呵呵,
作者: intermec    时间: 2009-12-22 21:19
LZ的例子看得不是很明白阿,哪位大大能说得具体的吗,,我太菜了,,,或是举个简单的点例子阿???
作者: yunqian09    时间: 2009-12-22 23:41
mark
作者: feiyang007    时间: 2009-12-23 00:22
学习了
作者: alexmayer    时间: 2009-12-23 10:01
学习了……
作者: mflyxy    时间: 2009-12-23 10:18
谢谢  学习
作者: cargle    时间: 2009-12-23 10:33
很不错
作者: lv998127    时间: 2009-12-23 10:50
标志下,准备学了
作者: shotstar    时间: 2009-12-23 12:13
不mark不行了
作者: wangff2531    时间: 2009-12-23 12:41
MARK GUI
作者: TornadoYu    时间: 2009-12-23 23:30
mark~~
作者: xyq4513    时间: 2009-12-24 10:25
mark~~
作者: 3.14159    时间: 2009-12-24 10:25
好东西
作者: eric_wang    时间: 2009-12-24 11:45
好贴,mark!
作者: shdzbsl    时间: 2009-12-24 12:44
mark
作者: our_avr    时间: 2009-12-24 13:58
mark.非常好的东西啊
作者: psl_87    时间: 2009-12-24 14:09
很不错,MARK
作者: yaya001    时间: 2009-12-24 14:34
MARK
作者: longfeixue    时间: 2009-12-24 15:41
慢慢学习
作者: blueagle    时间: 2009-12-24 15:45

作者: keaiduo    时间: 2009-12-24 15:47
学习一下····
作者: gz_dailin    时间: 2009-12-24 16:13
我也mark一下
作者: jackmo    时间: 2009-12-24 16:54
MARK
作者: wenwu    时间: 2009-12-24 17:09
思路不错。
作者: wobenchentu    时间: 2009-12-24 17:17
mark.......... 学习一下




欢迎光临 amobbs.com 阿莫电子技术论坛 (https://www.amobbs.com/) Powered by Discuz! X3.4