【再次】请教傻孩子: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)
}
} 为什么不能多状态分支?怎么不能使用邮箱?你到了特定的状态,就让邮箱发送消息过去啊,显示任务明显就是一个死循环,它也有很多分支啊,每个分支对应着你邮箱的各种分支。
建议看看<……>周航慈出的一本书,也就二百多页吧,专门讲UCOS的,现在已经出到第二版了,讲的还不错。当当上买一本吧。 void TASK_DISPLAY()
{
INT8U st1;
static INT8U self_n = 0; // 用于记录自检到什么地方
static INT8U err_time = 0; // 用于记录显示"Err"时间
while (1)
{
等待消息;
switch(status)
{
case :
case :
……
在没有各类消息的时候,该显示什么东东。
} 回复【楼主位】ba_wang_mao
-----------------------------------------------------------------------
老大!多谢你传的书。
书有第二版,和第一版不同,最后有个例子不错,看看就明白了! to 【楼主位】 ba_wang_mao
我觉得你缺少的是状态机思想……而不是如何使用UCOS……
你可以先考虑画出你心目中事情的处理流程图——然后发出来
我们大家帮你一起规划具体的模块布局,以及后续的处理方法
这样走一遍流程,我想你就能把握住一二了。 回复【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秒钟后,四个数码管重新将初始的参数值
显示在数码管上。
请帮忙指点。 我记得UCOS有一种消息通讯是不会挂起任务的。如果没有合适的,自己也可以写一个。
状态机就是基于信息交换以及信息触发的状态变化的。裸机下能解决的问题,操作系
统下完全也可以用同样的方法。 回复【6楼】Gorgon Meducer 傻孩子
我记得ucos有一种消息通讯是不会挂起任务的。如果没有合适的,自己也可以写一个。
状态机就是基于信息交换以及信息触发的状态变化的。裸机下能解决的问题,操作系
统下完全也可以用同样的方法。
-----------------------------------------------------------------------
你是说无等待消息队列吗? 这种方式有可能导致任务接收不到呀!不般用在中断服务程序中(防止中断假死) 嗯……那就自己构造一个吧~ MARK 如果能做一套GUI的库,一个界面用一个任务,就像GUI程序那样,不同的显示区域内容以控件的形式处理,整体上获得焦点的界面响应消息,可以参照windows的GUI那样处理消息。
不知道有没有这样的可以用于12864点阵的库? MARK 看了半天 是要做个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]