以上便是一个完整的程序。首先,这个程序有一个特点,就是没有main函数了。 下面,就对这个程序作出分析并对rtx51加深学习和理解。
void job() _task_ 0 {}, 这个,便是一个任务,所谓任务,就是披着嫁衣的函数。void,这个,名义上可有可无,但,有为好,一般不需要做什么返回。job()这个,就是函数名了。这个job可以随便一个名字,自己可以随便起。 然后_task_是一个关键字,必须要有,表示你建的这个函数就是一个任务。 然后 0呢, 表示这个任务的优先级是0。拥有最高优先级。
因为,使用rtx51这个,并没有main函数,所以,程序是从任务0开始的,然后,做任务0开始执行的后,程序该干嘛就干嘛了。那现在看一下任务0干了嘛。
os_create_task (1); ,这个,就是任务0做的事。就是创建了任务1。因为 void num1() _task_ 1 {}只是定义了任务1的函数,或者只是定义了任务1该干什么的。但,程序没有调用到它,它就还不能正常工作。所以os_create_task (1);的工作就是调用了任务1,让任务1可以正常工作。然后,把任务1创建后,就和任务0无关了。同理,也可以os_delete_task(1);来删除任务1,这样,删除了任务1后,任务1里的内容就不再工作了。
rtx51tiny这个可以定义16个任务。16个任务,对于用51实现的系统,基本就可以了。有一些初学者有点困惑的是,以为程序只是定义16个函数,这里只是说最大支持16个任务,而你要定义各种函数呢,定义多少个都可以的。
然后,现在就是每个任务的作用,联系及区别了。
以上程序定义了0,1,2,3共四个任务。
任务0所做的是:
while(1)
{
P1=~P1;
os_wait(K_TMO,50,0);
}
就是在一定的时间间隔里,对P1的值取反。os_wait(K_TMO,50,0);这个函数就是等待时间溢出,具体参考os_wait()这个函数。K_TMO表示是对时间溢出的方式做出等待,K_SIG,这个表示对信号作出等待。如果用到了K_SIG,就要用到os_send_signal 这个函数,表示对某个任务发送信号。然后,那个函数接收到了另一个任务接收到的信号,就跳出等待,作出下一步的指令。这个的50呢,表示的是表示50个时 间间隔。就像刚才在厨房里的时间间隔为10分钟,那这里就等了50个分钟。在rtx51默认的时间间隔是0.01s,也就是10ms,100Hz.,那 50个时间间隔,就是间隔了0.5s,那任务0的功能就是每隔0.5来对P1的状态取反。
同理,分析任务1就不难了。 也有一些人疑惑了,每个任务里都有一个while()循环,程序都进入了死循环,怎么再执行其它的指令呢。
所 以,在这里需要接受的概念就是,每一个任务被建立之后,就不再管其它任务了,就自己在做自己的事了。每个程序就相当于一个main函数一样了。或者这么 说,一个12Mhz的晶振,你定义了12个任务,然后,这个CPU就被分成12个CPU,每一个CPU的时钟频率为1Mhz,然后,每个CPU就在做自己 的事,和其它CPU无关,只是两个CPU之间是可以通信管理了。这样的解释虽然不恰当,不过,还是很形象地让不少同学接受了这个概念。
以上便是一个简单的多任务管理了。它有什么优点,这个, 就看你程序的用途了。举个简单的说法吧,比如你要用51单片机实现键盘的扫描,又要实现数码管 的动态扫描显示,还要实现通信,管理,控制等信息。其中一点,要做到键盘的扫描,就必须让程序至少在每10ms内或者更严格的时间里,对键盘作出扫描,那 么,这个扫描程序如果用中断来实现的话,还是可以接受的,但如果不是用中断,而是在非中断程序里实现的话,但,你的程序还是要做其它事的,而且程序在做其 它的事的情况下,还要照顾的键盘的扫描。还有数码管的动态扫描,如果用定时中断来说才能保证程序不因其它指令的执行而影响了数码管显示的延迟或不稳定。但 要保证这些都要照顾到,程序写起来就毕竟麻烦了。但如果采用了这种多任务的方式的话,就免去了这个麻烦了。比如,键盘扫描就定义成一个任务,这样,这个任 务的工作就是键盘的扫描,其它事也不做,这样,就不受其它程序段的影响,而且这个任务也可以方便的移植到相同的系统中去。数码管的显示也定义一个任务来实 现。
比如你还想添加一个超声波的显示上去,那么,你只要再定义多一个任务用来作超声波测距的就可以了。对原有程序几乎不需要作修改,而且对原来的程序结构也不改变。
|