搜索
bottom↓
回复: 568

发一个裸机下的界面编写方式.,,不用结构体,,设计简单,思路清晰,没有死循环,,,,使用

  [复制链接]

出0入0汤圆

发表于 2009-12-10 11:02:34 | 显示全部楼层 |阅读模式
发一个代码.也是本人在长期的写程序中慢慢摸索出来的,不敢说是独创..也算是原创.呵呵,,

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

大体说明一下.

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


每个界面有一个标记STS


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


....

不多说了,,
个人在多个项目中使用过,稳定性很好.
没有使用那些乱七八糟的定时器,中断之类的东西,,,

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2009-12-10 11:26:51 | 显示全部楼层
这方法确实思路清晰,但程序大时候,占用程序空间相对较大,很多的switch
曾经用过.深有感触

出0入0汤圆

 楼主| 发表于 2009-12-10 12:18:02 | 显示全部楼层
是啊,,一个界面一个SWITCH,

反过来想,,
无论用什么方法写,都是在一个界面里来操作按键,怎么着也得去做按键的对应处理,,,

出0入0汤圆

发表于 2009-12-10 12:53:10 | 显示全部楼层
MARK GUI

出0入296汤圆

发表于 2009-12-10 13:12:54 | 显示全部楼层
呵呵……恭喜LZ也摸索出这种模式了哈。这种工程模式我已经用很久了!不过我不使用switch,因为
局限性很大,每个状态机通常只能有一条执行线路。我使用if结构,这样每个状态机可以有多个并发
的执行线路。我注意到,你的代码中还没有使用调度器。其实配合这种状态机系统,可以用很简单的
合作式调度器来控制状态机的启动状态。有兴趣可以参考我的一些代码。
同时,配合这种编程方式,我正在酝酿一种可视化集成开发环境。哎……可惜一直没有时间实施……

出0入0汤圆

发表于 2009-12-10 13:26:32 | 显示全部楼层
【4楼】 Gorgon Meducer 傻孩子
"我注意到,你的代码中还没有使用调度器。其实配合这种状态机系统,可以用很简单的
合作式调度器来控制状态机的启动状态。有兴趣可以参考我的一些代码。
"

Gorgon Meducer 傻孩子
您曾写的哪个代码有用到过这种方式的?很想学习下.

出0入0汤圆

发表于 2009-12-10 13:28:57 | 显示全部楼层
4楼,能否发一个按LZ所说方式、基于合作式调度器的例子?

出0入0汤圆

发表于 2009-12-10 13:34:19 | 显示全部楼层
顶一个

出0入0汤圆

发表于 2009-12-10 14:16:16 | 显示全部楼层
好贴,再顶顶!

出0入0汤圆

发表于 2009-12-10 14:33:46 | 显示全部楼层
以下是我的裸机界面,可以参考下

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();
    }           

}

出0入0汤圆

发表于 2009-12-10 17:46:28 | 显示全部楼层
标记下,会火

出0入0汤圆

发表于 2009-12-10 18:19:20 | 显示全部楼层
MARK一下,谢谢。

出0入0汤圆

发表于 2009-12-10 18:34:03 | 显示全部楼层
排队学习

出0入0汤圆

发表于 2009-12-10 18:58:17 | 显示全部楼层
[Gorgon Meducer 傻孩子]:
    请把你的代码上传来看下,谢谢!

出0入0汤圆

发表于 2009-12-10 19:35:48 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-12-10 19:57:31 | 显示全部楼层
关注下

出0入0汤圆

发表于 2009-12-10 20:00:24 | 显示全部楼层
很好,顶

出0入0汤圆

发表于 2009-12-10 20:22:34 | 显示全部楼层
Gorgon Meducer 傻孩子

可否把您的相关代码贴上来学习一下,谢谢。

出75入4汤圆

发表于 2009-12-10 20:51:48 | 显示全部楼层
不错,学习经验。

出0入0汤圆

发表于 2009-12-10 20:55:12 | 显示全部楼层
值得参考啊,谢谢!

出0入0汤圆

发表于 2009-12-10 21:05:52 | 显示全部楼层
真正有价值的怎能不标。。。。。个。。记。

出0入0汤圆

发表于 2009-12-10 21:32:32 | 显示全部楼层
傻孩子,都在等你!

出0入0汤圆

发表于 2009-12-10 21:36:39 | 显示全部楼层
灵活运用C语言的 结构体 和 指针,可以达到 事半功倍 的效果~

出200入0汤圆

发表于 2009-12-10 22:50:13 | 显示全部楼层
记号

出0入0汤圆

发表于 2009-12-10 23:12:25 | 显示全部楼层
顶一个

出0入0汤圆

发表于 2009-12-10 23:21:57 | 显示全部楼层
偶用函数指针表....

出0入0汤圆

发表于 2009-12-10 23:22:17 | 显示全部楼层
记号

出0入0汤圆

发表于 2009-12-10 23:29:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-10 23:32:41 | 显示全部楼层
mark,等傻孩子

出0入0汤圆

发表于 2009-12-11 00:15:53 | 显示全部楼层
等傻孩子的方案

出0入296汤圆

发表于 2009-12-11 09:57:50 | 显示全部楼层
我这里有两个调度器,一个是过去用的简单版本,一个是后来的改进版本,但是原理都基本一样。
这里我只说一下原理:
所有的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结构
看成一个线程。这也符合“进程含有资源”,“线程通常不含有资源”的描述。

有兴趣的人可以发现,我的很多代码都是这种结构的。

出0入0汤圆

发表于 2009-12-11 10:01:15 | 显示全部楼层
期待傻孩子更详细的论述!

出0入0汤圆

发表于 2009-12-11 10:12:10 | 显示全部楼层
之前我也用这种状态机的方法来编写,,,但是我后来发现使用一些简单的时间片调度系统,更方便。

出0入296汤圆

发表于 2009-12-11 10:13:02 | 显示全部楼层
老版本简易调度器
点击此处下载 ourdev_513080.rar(文件大小:8K) (原文件名:FSM_EASY.rar)

新版本调度器
点击此处下载 ourdev_513081.rar(文件大小:28K) (原文件名:FSM_V2.rar)

出0入0汤圆

发表于 2009-12-11 10:17:43 | 显示全部楼层
好东西

出0入0汤圆

发表于 2009-12-11 16:09:24 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-11 18:36:31 | 显示全部楼层
顶~

出0入0汤圆

发表于 2009-12-11 18:45:17 | 显示全部楼层
不能不顶

出10入0汤圆

发表于 2009-12-11 20:51:23 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-12-12 00:44:42 | 显示全部楼层
MARK

出0入0汤圆

 楼主| 发表于 2009-12-12 01:38:48 | 显示全部楼层
看来我这块砖扔的还行...

出0入0汤圆

发表于 2009-12-12 08:09:33 | 显示全部楼层
好帖马克之

出0入0汤圆

发表于 2009-12-12 08:18:14 | 显示全部楼层
jh

出0入0汤圆

发表于 2009-12-12 08:27:57 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-12 08:50:08 | 显示全部楼层
记号,有时间仔细看看。

出0入0汤圆

 楼主| 发表于 2009-12-13 11:03:52 | 显示全部楼层
参考了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)

出0入147汤圆

发表于 2009-12-13 11:24:00 | 显示全部楼层
不错 有空慢慢看

出0入0汤圆

发表于 2009-12-13 11:24:44 | 显示全部楼层
学习一下。

出0入0汤圆

发表于 2009-12-14 19:54:49 | 显示全部楼层
顶楼主,加盖一层楼!

出0入0汤圆

发表于 2009-12-14 20:04:40 | 显示全部楼层
Mark

出0入18汤圆

发表于 2009-12-14 21:13:51 | 显示全部楼层
MK

出0入0汤圆

发表于 2009-12-18 17:59:09 | 显示全部楼层
标记。

出0入0汤圆

发表于 2009-12-18 19:44:39 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-18 19:57:25 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-18 20:35:12 | 显示全部楼层
mark,学习一下!

出10入95汤圆

发表于 2009-12-18 22:52:04 | 显示全部楼层
标记!

出0入0汤圆

发表于 2009-12-18 23:37:42 | 显示全部楼层
不错!学习了

出0入0汤圆

发表于 2009-12-19 22:28:37 | 显示全部楼层
看了半天,我没看懂状态机,我的多层界面采用索引
//定义按键功能指针
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;
        }
}
}

}

出0入0汤圆

发表于 2009-12-20 10:37:10 | 显示全部楼层
不错!学习了

出0入0汤圆

发表于 2009-12-20 13:45:50 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-12-20 13:46:31 | 显示全部楼层
学习,好好学习!

出0入0汤圆

发表于 2009-12-20 13:54:06 | 显示全部楼层
也贴一个界面处理的函数,
根据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;
          }
        }
/*********************帮助响应结束*********************/
}

出0入0汤圆

发表于 2009-12-20 14:15:35 | 显示全部楼层
火了
mark

出75入4汤圆

发表于 2009-12-20 14:28:59 | 显示全部楼层
此贴火了。

出0入0汤圆

发表于 2009-12-20 16:31:15 | 显示全部楼层
mark

出0入4汤圆

发表于 2009-12-20 16:51:49 | 显示全部楼层
mark.学习

出0入0汤圆

发表于 2009-12-21 00:25:39 | 显示全部楼层
marl

出0入0汤圆

发表于 2009-12-21 00:35:53 | 显示全部楼层
MARK

出0入4汤圆

发表于 2009-12-21 07:58:06 | 显示全部楼层
程序当然得这么写喽,看网上人家写的GSM发短信程序,发一个while一下,发一个while一下,别的活还要不要干啦
SWITCH与IF各有千秋,

出0入0汤圆

发表于 2009-12-21 08:34:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-21 08:39:45 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-21 09:30:15 | 显示全部楼层
先mark 慢慢学习

出0入0汤圆

发表于 2009-12-21 09:47:40 | 显示全部楼层
mark

出95入100汤圆

发表于 2009-12-21 15:08:33 | 显示全部楼层
慢慢看,不过跟写个结构体,然后用函数指针有多大的区别?

出0入0汤圆

发表于 2009-12-21 15:28:30 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-21 16:32:06 | 显示全部楼层
越简单越灵活,呵呵,

出0入0汤圆

发表于 2009-12-22 21:19:49 | 显示全部楼层
LZ的例子看得不是很明白阿,哪位大大能说得具体的吗,,我太菜了,,,或是举个简单的点例子阿???

出0入0汤圆

发表于 2009-12-22 23:41:08 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-23 00:22:19 | 显示全部楼层
学习了

出0入0汤圆

发表于 2009-12-23 10:01:49 | 显示全部楼层
学习了……

出0入0汤圆

发表于 2009-12-23 10:18:00 | 显示全部楼层
谢谢  学习

出0入0汤圆

发表于 2009-12-23 10:33:23 | 显示全部楼层
很不错

出0入0汤圆

发表于 2009-12-23 10:50:09 | 显示全部楼层
标志下,准备学了

出0入0汤圆

发表于 2009-12-23 12:13:43 | 显示全部楼层
不mark不行了

出0入0汤圆

发表于 2009-12-23 12:41:16 | 显示全部楼层
MARK GUI

出0入0汤圆

发表于 2009-12-23 23:30:30 | 显示全部楼层
mark~~

出0入0汤圆

发表于 2009-12-24 10:25:09 | 显示全部楼层
mark~~

出0入0汤圆

发表于 2009-12-24 10:25:45 | 显示全部楼层
好东西

出0入0汤圆

发表于 2009-12-24 11:45:20 | 显示全部楼层
好贴,mark!

出0入0汤圆

发表于 2009-12-24 12:44:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-24 13:58:47 | 显示全部楼层
mark.非常好的东西啊

出0入0汤圆

发表于 2009-12-24 14:09:38 | 显示全部楼层
很不错,MARK

出0入0汤圆

发表于 2009-12-24 14:34:12 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-12-24 15:41:04 | 显示全部楼层
慢慢学习

出0入0汤圆

发表于 2009-12-24 15:45:22 | 显示全部楼层

出0入0汤圆

发表于 2009-12-24 15:47:05 | 显示全部楼层
学习一下····

出0入0汤圆

发表于 2009-12-24 16:13:30 | 显示全部楼层
我也mark一下

出0入0汤圆

发表于 2009-12-24 16:54:09 | 显示全部楼层
MARK

出0入0汤圆

发表于 2009-12-24 17:09:04 | 显示全部楼层
思路不错。

出0入0汤圆

发表于 2009-12-24 17:17:42 | 显示全部楼层
mark.......... 学习一下
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 23:14

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表