ba_wang_mao 发表于 2011-3-25 11:39:07

【再次】请教傻孩子:uCOS/II中,如何设计一个多状态分支的“显示任务”

问题提出:在前后台中,有如下一个多分支的“显示子程序”
   
定义一个全局变量 status,用来记忆“显示状态”分支。

(1)、初始化时,status = “仪表上电自检”   
      上电自检有以下两个目的:
      (a)、检查仪表上的数码管好坏情况
      (b)、显示仪表版本号   

(2)、上电自检大约需要3秒钟   
         第一个 500ms,四个数码管显示“1111”   
         第二个 500ms,四个数码管显示“2222”   
         第三个 500ms,四个数码管显示“3333”   
         第四个 500ms,四个数码管显示“8888”
         第五个 500ms,四个数码管显示“版本号”
         第六个 500ms,status = “测量模式”   

(3)、当status = “测量模式”时
      按下面板上的《编程》键,切换到编程模式,即status = “编程”。
      编程模式时,四个数码管显示待修改参数的参数值

(4)、当status = “编程”时
      用户按下《确认》键,确认修改时,如果参数超限,则 status = “编程错误”。
      数码管持续显示“err”,并维持1秒钟。



   在uCOS/ii中,数据通信一般有以下三种:

1、全局变量
2、消息邮箱
3、消息队列

(A).假如使用消息邮箱的话,用在周期性显示任务上显然不合适 ,不可能因为没有等到消息,显示任务就挂起等待吧!   
(B).假如使用消息队列的话,用在周期性显示任务上显然也不合适,不可能因为没有等到消息,显示任务就挂起等待吧!   
(C).如果使用全局变量,由于“生产者”可能在定时中断,也可能是其它任务,因此必须用
OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()保护原子。

   
以下是我的OS代码构思,请指正:

INT8U status = "仪表上电自检";

void TASK_DISPLAY()
{
   INT8U st1;
   static INT8U self_n = 0;   // 用于记录自检到什么地方
   static INT8U err_time = 0; // 用于记录显示"Err"时间
   while (1)
    {
      OS_ENTER_CRITICAL();
      st1 = status; // 使用全局变量进行数据通信
      OS_EXIT_CRITICAL();

      switch (st1)
       {
          case 仪表上电自检:
               self_n++;         //
               switch (self_n)
               {
                   case 0:
                      数码管显示 1111;
                      break;
                   case 1:
                      数码管显示 2222;
                      break;
                   case 2:
                      数码管显示 3333;
                      break;
                   case 3:
                      数码管显示 8888;
                      break;
                  case 4:
                      数码管显示 “仪表版本号”;
                      break;
                   case 5:
                      status = “测量”; // 自检完毕,切换状态机="测量"
                      break;
               }
               break;   
         
          case 编程模式:
               四个数码管显示待修改参数的参数值
               ; 还要处理在编程时,数码管闪烁(用于指示当前正在编辑哪一个数码管对应的数值)
               break;   
         case 编程错误:   
               数码管显示 "Err";
               err_time ++;
            if (err_time >= 2)
            {
                  err_time = 0 ;
                  status = “编程”; // 显示"Err"1秒钟后,切换状态机="编程"
            }   
            break;   
         case 测量模式:   
            四个数码管显示测量数据
            break;   
      }   

      OSTimeDelay(50); // 延时节拍(延时500ms)   
}   

}

kinsno 发表于 2011-3-25 11:47:24

为什么不能多状态分支?怎么不能使用邮箱?你到了特定的状态,就让邮箱发送消息过去啊,显示任务明显就是一个死循环,它也有很多分支啊,每个分支对应着你邮箱的各种分支。

建议看看<……>周航慈出的一本书,也就二百多页吧,专门讲UCOS的,现在已经出到第二版了,讲的还不错。当当上买一本吧。

kinsno 发表于 2011-3-25 11:49:54

void TASK_DISPLAY()
{
   INT8U st1;
   static INT8U self_n = 0;   // 用于记录自检到什么地方
   static INT8U err_time = 0; // 用于记录显示"Err"时间
   while (1)
    {
            等待消息;         
            switch(status)
            {
               case :
               case :
               ……
               在没有各类消息的时候,该显示什么东东。
            }

catvevs 发表于 2011-3-25 11:56:44

回复【楼主位】ba_wang_mao
-----------------------------------------------------------------------

老大!多谢你传的书。
书有第二版,和第一版不同,最后有个例子不错,看看就明白了!

Gorgon_Meducer 发表于 2011-3-25 12:09:32

to 【楼主位】 ba_wang_mao
    我觉得你缺少的是状态机思想……而不是如何使用UCOS……
你可以先考虑画出你心目中事情的处理流程图——然后发出来
我们大家帮你一起规划具体的模块布局,以及后续的处理方法
这样走一遍流程,我想你就能把握住一二了。

ba_wang_mao 发表于 2011-3-28 10:30:19

回复【4楼】Gorgon Meducer 傻孩子
to 【楼主位】 ba_wang_mao
    我觉得你缺少的是状态机思想……而不是如何使用ucos……
你可以先考虑画出你心目中事情的处理流程图——然后发出来
我们大家帮你一起规划具体的模块布局,以及后续的处理方法
这样走一遍流程,我想你就能把握住一二了。
-----------------------------------------------------------------------

不是状态机的问题,是对任务之间通信的理解上。

   在前后台中,只需要函数或者全局变量既可实现子程序之间的通信,而且可以随心所欲的使用。
   
   但是在UCOS中,任务之间通信必须通过系统提供的API函数进行通信。也就是说两个任务之间必须对过第三方来进行通信,不像前后台那样,子程序之间可以随心所欲的使用。

   1、显示任务如果使用信号量的话:当没有等到信号时,该任务就会挂起
   2、显示任务如果使用消息队列的话:当没有等到消息时,该任务就会挂起。

   而我设计的显示任务显然是一个周期性任务。其一般格式如下
   task ()
   {
         初始化;
         while (1)
         {
            任务代码;
            延时节拍;   // 系统提供的API函数
         }
   }

    我要设计的显示任务需要完成的功能如下:

       (1)、仪表上电自检后,“四个”数码管每隔500ms依次显示“1111”,“2222”,“3333”,“版本号”。
       (2)、自检完成后,四个数码管显示测量数据
       (3)、用户按面板上的《编程》键后,四个数码管显示“待设置的参数值”,同时当前正编程的数码管位置开始闪烁
       (4)、当编程状态时,用户按下面板上的《确认》键,如果参数在合法的范围内,则保存当前参数值,然后自动将下一个待设置的参数值显示在数码管上;
            否则,当设置的参数值超出范围,则数码管显示“Err”,同时数码管持续1秒钟内都显示“Err”,1秒钟后,四个数码管重新将初始的参数值
显示在数码管上。


    请帮忙指点。

Gorgon_Meducer 发表于 2011-3-28 11:12:40

我记得UCOS有一种消息通讯是不会挂起任务的。如果没有合适的,自己也可以写一个。
状态机就是基于信息交换以及信息触发的状态变化的。裸机下能解决的问题,操作系
统下完全也可以用同样的方法。

ba_wang_mao 发表于 2011-3-28 11:38:37

回复【6楼】Gorgon Meducer 傻孩子
我记得ucos有一种消息通讯是不会挂起任务的。如果没有合适的,自己也可以写一个。
状态机就是基于信息交换以及信息触发的状态变化的。裸机下能解决的问题,操作系
统下完全也可以用同样的方法。
-----------------------------------------------------------------------

你是说无等待消息队列吗? 这种方式有可能导致任务接收不到呀!不般用在中断服务程序中(防止中断假死)

Gorgon_Meducer 发表于 2011-3-28 12:53:22

嗯……那就自己构造一个吧~

Helloeveryon 发表于 2011-10-15 18:53:28

MARK

dzmcs 发表于 2011-10-15 20:05:53

如果能做一套GUI的库,一个界面用一个任务,就像GUI程序那样,不同的显示区域内容以控件的形式处理,整体上获得焦点的界面响应消息,可以参照windows的GUI那样处理消息。

不知道有没有这样的可以用于12864点阵的库?

Helloeveryon 发表于 2011-11-20 08:32:11

MARK

adce 发表于 2011-12-19 19:04:33

看了半天 是要做个Windows2000那样的进度条吧...

定义一个全局变量和全局数组都行...假如是一个变量 a = 0;
Create 2个任务...
一个是自检任务 假如有4个过程 每个检查完后 a++;
另一个是显示任务 双while
main()
{
   GUI_Init()
   while(a<4)
   {
      画进度条
      GUI_Delay(100);
   }
   程序界面
   while(1)
   {
      GUI_Delay(100);
   }
}

全局变量是任务沟通的唯一方式吧...再花花的模式也是用全局变量...只不过不让你知道而已...

ucos除了初始化部分并不需要用户调用OS_ENTER_CRITICAL()....除非结构有问题...
页: [1]
查看完整版本: 【再次】请教傻孩子:uCOS/II中,如何设计一个多状态分支的“显示任务”