51单片机如何跳出wile循环_天问51学习笔记(2):搭建新的uCOS II操作系统平台...

就像落户是一回事,安家则是另一回事一样,虽然作为开始的将特定范例的uCOS II移植成功很重要,但在开发板上搭建新uCOS II系统平台更重要,它是所有自己开发uCOS II实时多任务程序的起点。

虽然上文的uCOS II移植成功了,但是该范例很具体,还需要修改。比如该范例只闪了一个灯,新范例应该做8个LED的流水灯。该范例工作主频设死在24MHz,新范例应该可以改变。该范例使用定时器0,新范例应该可以使用其他定时器。下面就为大家介绍如何在天问51上搭建新的uCOS II操作系统平台。

(一)main函数框架

(1)构造新系统程序框架

搭建新平台的目的是让用户在这个平台上编写自己的多任务程序,所以要先构造和实现一个通用的、典型的和可扩展的系统程序框架,其中最主要的就是构造main函数框架。下图为新平台的main函数。

0223d7c2921d117c6bd9b0b2cbd6df3b.png

(2)操作系统必须要有驱动程序支持,这样用户就能比较简单地对系统进行设置和编程。

新系统专门建了一个“STC8”的子目录,其中有“TW51_DRV_P6”天问51的P6端口设备的驱动程序和“CYx51_DRV_PxT5S1”STC8系列单片机的8个端口、5个定时器和串口1的设置程序,用户只要调用接口函数就可以完成系统设置。

第39行和第40行是这两个驱动程序的头文件包含语句。

(3)第47行是原来范例的系统初始化程序,现在已经删掉了原来定时器0和串口1的初始化程序,只保留了uCOS II的初始化程序和串口1环形缓冲区的初始化程序。

ce4ea191a454fad91ff0e1b5f54fbc7a.png

(4)为避免意外,对定时器中断之类的设备进行设置,应该要在关闭中断的情况下进行,第50行先关闭中断进行系统设置,设置完成后第71行再打开。

(5)原来范例的主频为24MHz。第53行将单片机系统的主频设置为40MHz,对于天问51开发板,笔者一直用这个主频,运行很稳定。用户可以根据自己的需要设置主频,只是烧录时也要选择同样的主频进行烧录。

第54行将STC8H的所有8个端口先预设为准双向端口。

第61行将串口1的波特率设置为115200,用户可以根据自己的需要修改。第62行打开串口1中断。

第65行对天问51开发板进行初始化,第68行打开LED8设备进行流水灯显示。其中的原理见笔者的上一篇文章,这里就不再细述了。

(6)原来范例驱动任务调度是定时器0,中断频率仅为50赫兹,其任务调度时间为20毫秒。STC8H是一款高性能单片机,主要用于各种高速场合,所以新平台将任务调度频率设置为1KHz,对应任务调度时间(uCOS II的实时响应时间)为1毫秒。

为通用计新平台用定时器4作任务调度用,第47行将定时器4的溢出频率设定为1000Hz,第58行显式地打开定时器4中断。

用户可以根据自己的需要选择驱动uCOS II任务调度中断的定时器和驱动频率,除了修改第57行和58行,还要修改以下两个地方:

“os_cfg.h”头文件中的每秒多少个Tick的定义

0d4e75de6278505e2df7b2ac88342952.png

以及“OS_CPU_A.A51”中的定时器中断服务程序:

f9b8e012e32798a4ba694fa88044ccf3.png

其中将第389行的原范例定时器0的中断地址0x000B,修改为第390行的新系统定时器4的中断地址0x00A3。

其中将第418行的原范例定时器0的停止工作指令,修改为第419行的新系统定时器4的停止工作指令。

其中将第423行的原范例定时器0的开始工作指令,修改为第424行的新系统定时器4的开始工作指令。

注:关闭任务调度定时器的计数,这一直是uCOS II移植到8051单片机时采用Keil编译器必须的一个不得而已的措施,原因是采用的临界区保护的方法1是不具备嵌套功能的:

fee26687df732039656aae4ea8055e4a.png

当然上面的关闭定时器工作的方法也不具备嵌套功能,所以用户在使用临界区保护时一定要注意,避免无意中打开中断,产生意外。这种不具备嵌套功能的类似例子是Keil编译器的块注释功能“/*”和“*/”的配对问题。

下图是main函数的后半部分:

1db9e3a51e3a3f46cf26684fa357f38a.png

(7)按照uCOS II提倡的多任务程序框架,第74行首先建立用户的第一个任务,其他的任务由这个任务来建立。

(8)为了与无专门操作系统的STC单片机程序结构一致,第77行到第83行形成了一个后台任务主循环,其中第80行启动uCOS II的任务调度,将CPU的程序执行权交给优先级最高的就绪任务。

注:首次执行第80行的启动多任务调度程序,第80行“OSStart()”便不会再退出,因此第83行的程序永远不会得到执行,放在这里只是一个形式,提醒用户不要在第80行后再添加任何程序行。

(二)建立用户自己的任务程序

下面以流水灯为例,介绍建立用户自己程序的方法和用户程序的基本结构。

6bd347f7ec13d0cf09d5edc5cd684735.png

(1)第110行到第112行依次建立了三个用户程序,其中后两个是原来范例的。

第122行到第140行是流水灯任务函数。

(2)第127行和第128行是任务的初始化部分。其中第127行是套路,虽然uCOS II允许第一次启动某个任务时向其传入参数,但是一般的任务都不使用这个参数,为避免Keil编译器提示警告信息,所以采用这个套路。

(3)从结构看,uCOS II的用户任务普通的任务一样,具有一个永不退出的主循环。

由于uCOS II的任务不是用“LCALL”指令来启动的,并且只会被启动一次,因此虽然用户任务用函数的形式来编写,但是直接退出用户函数会导致系统崩溃。

如果用户实在不需要这个函数了,唯一正确的方法就是使用第114行这个语句,把自己杀死。

(4)在一般的用户程序里,总会有一些时候不需要做任何事,等待某个事件的发生,就像在流水灯程序中,需要延时一段时间。这时就可以用uCOS II规定的方法通知操作系统,放弃任务自己的执行权,等待事件发生后再唤醒自己。

第135行是uCOS II中最典型任务延时函数,它暂时放弃执行权,让操作系统在几点、几分、几秒和几毫秒钟后唤醒自己。它的函数接口为:

fd4a31e76e6eaa21c70b9a5b652079d5.png

(5)流水灯任务使用了P6端口,如果其他任务也使用P6端口怎么办?这个就是多任务程序设计中特别需要考虑的地方。

在STC8单片机上,使用Keil编译器,用户在程序的任何地方都可以访问“SFR”和“XSFR”这样的公共资源,比如通过写“SBUF”特殊功能寄存器通过串口1向外发送一个字符。

如何协调各个任务使用这种公共资源,大体有5种方法:

1)用户自己控制。通常简单的单片机系统程序是一个程序员独立完成的,程序员自己决定怎么控制。

2)抢占式。用户不需要多考虑,哪个任务逮住哪个任务直接使用。就像本文上面的流水灯范例一样。

3)临界区保护法。就像被移植的范例中一样:

feeb9bfc28134551ab3be7746311931a.png

把第168行的端口操作当作“临界资源”,用第167行和第169行这样的保护临界区保护语句来保护,防止其他任务在自己操作临界资源时产生干扰,保证对临界资源的操作的完整性。

这种保护方法对于需要保证机械设备动作连续执行的应用是一种很实用的程序设计方法。

4)系统控制设备方法。像本范例中的串口1设备,采用环形缓冲区组装为一个设备,然后通过设备控制程序接口来操作。

5)不过,一般设备也可以同时被多个任务使用。因此对于需要独占使用某个设备的任务,就要对设备加锁。当然加锁的操作还要防止任务死锁,这是后话。

(三)总结

本文以流水灯程序为例给出了在天问51开发板上建立uCOS II实时多任务操作系统平台的方法,包括使用多少主频,采用哪个定时器,以多高的频率调度任务,以及如何初始化天问51开发板和编写用户自己的任务程序。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部