UCOS II例程文档格式.docx

上传人:b****2 文档编号:877410 上传时间:2023-04-29 格式:DOCX 页数:12 大小:281.31KB
下载 相关 举报
UCOS II例程文档格式.docx_第1页
第1页 / 共12页
UCOS II例程文档格式.docx_第2页
第2页 / 共12页
UCOS II例程文档格式.docx_第3页
第3页 / 共12页
UCOS II例程文档格式.docx_第4页
第4页 / 共12页
UCOS II例程文档格式.docx_第5页
第5页 / 共12页
UCOS II例程文档格式.docx_第6页
第6页 / 共12页
UCOS II例程文档格式.docx_第7页
第7页 / 共12页
UCOS II例程文档格式.docx_第8页
第8页 / 共12页
UCOS II例程文档格式.docx_第9页
第9页 / 共12页
UCOS II例程文档格式.docx_第10页
第10页 / 共12页
UCOS II例程文档格式.docx_第11页
第11页 / 共12页
UCOS II例程文档格式.docx_第12页
第12页 / 共12页
亲,该文档总共12页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

UCOS II例程文档格式.docx

《UCOS II例程文档格式.docx》由会员分享,可在线阅读,更多相关《UCOS II例程文档格式.docx(12页珍藏版)》请在冰点文库上搜索。

UCOS II例程文档格式.docx

voidUART0_Ini(void)

{uint16Fdiv;

U0LCR=0x83;

Fdiv=(Fpclk/16)/UART_BPS;

U0DLM=Fdiv/256;

U0DLL=Fdiv%256;

U0LCR=0x03;

}

voidUART0_SendByte(uint8data)

{U0THR=data;

//·

cent;

Euml;

Iacute;

Ecirc;

yacute;

frac34;

Yacute;

while((U0LSR&

0x40)==0);

//&

micro;

acute;

Yacute

intmain(void)

{

OSInit

();

OSTaskCreate(Task0,(void*)0,&

TaskStk[TaskStkLengh-1],0);

TASK1=OSSemCreate(0);

TASK2=OSSemCreate(0);

TASK3=OSSemCreate(0);

TargetInit();

OSStart();

return0;

/*******************************************************************************************

**Task0&

*******************************************************************************************/

voidTask0(void*pdata)

UART0_Ini();

OSTaskCreate(Task1,(void*)0,&

TaskStk1[TaskStkLengh-1],9);

OSTaskCreate(Task2,(void*)0,&

TaskStk2[TaskStkLengh-1],10);

OSSemPost(TASK1);

//通过发送信号量使Task0就绪

for(;

;

{

OSSemPend(TASK1,10,&

err)

//如果收到信号,则返回OS_NO_ERR,否则使TASK1进入等待

if(err==OS_NO_ERR)

UART0_SendByte(0x01);

OSSemPost(TASK2);

//通过发送信号量使Task1就绪,并进行任务调度

//使最高就绪态任务运行

}

/*******************************************************************************************Task1&

1

voidTask1(void*pdata)

{

OSSemPend(TASK2,10,&

err);

UART0_SendByte(0x02);

OSSemPost(TASK3);

voidTask2(void*pdata)

OSSemPend(TASK3,10,&

//&

raquo;

UART0_SendByte(0x03);

三个任务分别通过UART0输出0X01,0X02,0X03,可以学习理解信号量的基本用法及多任务的调度方法.

基于μC/OS-II的时间片调度法设计

45

 引言

  μC/OS-II嵌入式实时操作系统采用的是基于优先级的可剥夺调度法[1]。

基于优先级的可剥夺调度法是指,CPU总是让处于就绪态的、优先级最高的任务运行;

最高优先级的任务一旦就绪,总能得到CPU的使用权,当一个运行着的任务使一个比它优先级高的任务进入了就绪态时,当前任务的CPU使用权就被剥夺了,更高优先级的任务立刻得到了CPU的使用权。

除非最高优先级的任务主动放弃CPU的使用权(通过调用OSTimeDly()、OSSemPend()等函数),否则低优先级的任务是没机会获得CPU使用权的。

对于一个实际应用系统中耗时比较长的任务,为了让其他任务能够得到实时调度,可以用两种方法来处理。

第一种方法是把该任务的优先级设为最低(当然还是比空闲任务要高);

第二种方法就是让该耗时任务运行一段时间后延时一下再继续运行,即把整个任务划分为若干步骤来执行,如以下的示例代码:

  很多情况下,耗时长的任务并不能设置为最低优先级任务,而划分步骤来执行的方法不但繁琐而且每一步执行的时间也是不确定的(其他低优先级任务获得CPU使用权的时间也会是不确定的)。

笔者在用μC/OSII开发一款车载信息娱乐系统的时候就碰到了这样的问题,因此设计了一种优先级和时间片相结合的调度法(也就是基于μC/OSII的时间片调度法)。

  1调度原理

  这种调度法给处于就绪态的每一个任务都分配一个时间片(优先级越高分配的时间片越长,空闲任务得不到时间片的分配),内核按照任务的优先级依次调度处于就绪态的任务,即当就绪态中最高优先级的任务用完自己的时间片后,CPU控制权转让给就绪态中优先级第二高的任务。

该任务用完自己的时间片后,CPU控制权又转让给下一优先级的就绪态任务……当就绪态的每一个任务都被调度一次之后将重新为它们分配时间片,然后又开始新一轮的调度……[2]

  其中要注意的是,在调度过程中如果有一个比当前任务优先级更高的任务由其他态变成了就绪态(被创建或获取了一个信号量等),当前任务的CPU控制权将被剥夺;

空闲任务仍然是等到其他任务都退出就绪态才获得CPU的使用权。

  图1解释了该调度法的调度过程(其中任务1优先级最高,任务2次之,任务3最低)。

图1基于μC/OSII时间片调度过程

  ①任务2和任务3都处于就绪态,任务1在等待一个信号量,优先级中的任务2获得CPU使用权。

  ②任务2的时间片用完,优先级低的任务3获得CPU使用权。

  ③任务3的时间片用完,任务2重新获得CPU的使用权。

  ④任务2的时间片还没用完时中断来临,中断服务程序获得CPU使用权。

  ⑤中断服务程序发送了一个任务1等待的信号量,中断服务完成后优先级高的任务1获得CPU使用权。

  ⑥任务1的时间片用完,任务2继续运行。

  ⑦任务2的时间片用完,任务3获得CPU使用权。

  ⑧任务3的时间片用完,重新分配时间片,新一轮调度开始。

  2实现方法

  在调度算法的实现过程中,力求做到3点:

  ①尽可能少地改动μC/OSII原有的代码;

  ②增加的代码在风格上保持与原有的相一致;

  ③兼容原有的优先级调度法(可以很方便地选择优先级调度法或是时间片调度法)。

  注:

对于该小节中出现的代码,如果是笔者增加的部分都用黑体表示。

  2.1数据结构中增加的变量

  在进程控制块中增加两项:

  Typedefstructos_tcb{

  ……

#ifOS_TASK_TIME_SLICE_EN>

  /*条件编译,OS_TASK_TIME_SLICE_EN在os_cfg.h中定义,凡是涉及与时间片调度相关的代码都用条件编译。

这样,可以通过更改配置文件很方便地选择任务调度法

*/INT16UOSTCBTimeSlice;

  /*任务的时间片大小,在任务创建时被初始化,运行过程中保持不变*/

INT16UOSTCBCounter;

  /*任务运行剩余时间计数器,每一轮调度开始时该变量被赋值(等于OSTCBTimeSlice),运行过程中不断递减。

当其等于0时任务被剥夺CPU使用权*/

#endif

  }

  由于当前任务的时间片使用完时,该任务将被从就绪表OSRdyGrp以及OSRdyTbl[OS_RDY_TBL_SIZE]中清除;

新一轮调度开始时它又必须被恢复,因此笔者在uCOS_II.h文件中增加以下变量(不妨把它们称为“时间片调度表”)分别用于保存OSRdyGrp和OSRdyTbl[OS_RDY_TBL_SIZE]。

  OS_EXTINT8UOSTSSGrp;

  OS_EXTINT8UOSTSSTbl[OS_RDY_TBL_SIZE];

  另外,在uCOS_II.h文件中增加宏定义,用于表示任务时间片被用完这种状态:

  #defineOS_STAT_TS_USEUP0x40

 2.2相关函数的修改

  对OS_TCBInit()、OSTimeTick()、OSTimeDly()、OS_EventTaskWait()、OS_EventTaskRdy()这5个函数的修改,是在μC/OSII基础上实现时间片调度法的关键。

下面将一一对这几个函数的修改部分进行说明。

  在初始化任务控制块的函数OS_TCBInit()中,笔者添加以下代码让新创建的任务处于时间片就绪表中,并根据任务优先级对任务的时间片大小进行初始化。

  OSTimeTick()函数在每个时钟滴答被调用,在时间片调度过程中起到了递减时间片计数器的作用。

当计数器为0时,进行任务切换或是重新给各个任务分配时间片并开始新一轮调度。

  OSTimeDly()函数的作用是将任务延时一定的时间。

这种情况下,应该把该任务从时间片调度表中清除。

  当某个任务须等待一个事件的发生时,信号量、互斥型信号量、邮箱及消息队列会通过相应的PEND函数调用函数OS_EventTaskWait(),使当前任务从就绪任务表中脱离就绪态,此时还需把当前任务从时间片调度表中清除。

笔者在OS_EventTaskWait()函数中添加了以下代码:

  相应地,当某个事件发生了,信号量、互斥型信号量、邮箱及消息队列会通过相应的POST函数调用OS_EventTaskRdy(),从等待任务队列中使最高优先级任务脱离等待状态,此时还需要把该任务添加到时间片调度表中。

笔者在OS_EventTaskRdy()函数中添加了以下代码:

  OSTSSGrp|=bity;

  OSTSSTbl[y]|=bitx;

  3应用实例

  笔者首先把μC/OSII移植到开发板上(MCU是意法半导体生产的基于ARM7TDMI核的STR730[3]),然后如2小节所述对相关部分的源代码进行修改,接下来将优先级调度法和基于μC/OSII的时间片调度法进行比较。

为此分别建立了2个任务Task_TimeConsuming()、Task_Audio(),任务的优先级分别是5、6。

  由于模拟的耗时任务Task_TimeConsuming()是个死循环且没有调用OSTimeDly()函数,其优先级又比Task_Audio()高,如果完全按照优先级调度,系统不会有声音输出,因为负责声音控制的任务Task_Audio一直得不到运行。

而如果按照时间片调度(在os_cfg.h中增加#defineOS_TASK_TIME_SLICE_EN1),则声音输出正常,通过仿真器在Task_Audio()中设置断点,程序会很快停止在断点处。

进一步地,依次在Task_TimeConsuming()和Task_Audio()函数体中设置断点,分别记录两次PC指针停止在断点处时看门狗计数器的值WDG_Counter1和WDG_Counter2,可以利用WDG_Counter1和WDG_Counter2的差值估算出任务Task_Audio前后两次被调度的时间间隔(忽略任务在切换过程中的耗时)。

经过多次计算,这个时间间隔值的范围在58~59ms,而任务Task_TimeConsuming的时间片理论值=64-Prio=64-5=59ms,实验值与理论值是非常吻合的。

  当然,这只是简单的验证实验。

严格的测试还需要兼顾信号量、互斥型信号量、邮箱及消息队列相应的PEND、POST函数以及OSTimeDly()函数调用。

鉴于篇幅关系,这里就不再赘述了。

  结语

  笔者已经成功地把这种基于μC/OSII的时间片调度法运用到车载信息娱乐系统的开发中。

实践证明,对于含有耗时任务的系统,尤其是在需要严格控制耗时任务运行时间长度的场合,该调度算法会有一定的便捷性,也能保证系统的实时响应,而且整个算法只改动了μC/OSII中的少量代码;

还可以根据实际需要调整各个任务的时间片大小,体现出了算法的实用性与灵活性。

  

基于uC/OS-II的智能窗系统设计

35

随着电子技术的发展和人民生活水平的不断提高,智能窗已经越来越多地被用到了现代智能化建筑中,他提供住户一个安全、方便的环境。

据统计,在未来的几年内,安装智能窗的用户将不断增加。

本文讨论了一种基于实时操作系统μC/OS-II的智能窗设计方法。

1系统功能

本系统功能如下:

手动按钮开关窗户;

红外遥控窗户的开关;

雨天能够自动把窗户关闭;

检测到可燃气体自动把窗户打开;

遇有盗情,会发出刺耳的报警声,把窗户关闭,并发送一条短消息给住户。

2硬件设计

CPU的选择是嵌入式系统开发的关键所在。

本系统的CPU采用了ATMEL公司生产的AT89S51单片机。

主要基于以下几点考虑;

相比其他CPU价格便宜;

经过扩展后可以移植操作系统μC/OS-II;

51单片机在国内研究的较早,技术成熟。

系统还包括电源、存储、按键、煤气、湿度、盗情、电机等基本模块。

系统架构如图1所示。

3软件设计

3.1μC/OS-II简介

μC/OS-II是一个可移植(portable)、可固化的(rom-able)和占先式的(preemptive)实时内核,最多可以管理64个任务。

μC/OS-II的源代码公开,绝大部分代码使用标准的ANSIC书写,所以可以方便地移植到很多不同种类的处理器或控制器上。

μC/OS-II中的任务包括休眠态、就绪态、运行态、挂起态和被中断态5种状态。

3.2软件方案

3.2.1设计思路简介

本设计的软件和以往设计的前后系统不同,采用了多任务机制来设计应用程序。

CPU对大多数事件的处理都是放在任务中完成,而各个任务都是由对应的信号量激活的。

信号量可以由任务或外中断INT0来发送,各个任务和外中断INT0之间的关系如图2所示。

图2中的箭头代表向相应的任务发送相应的信号量,箭头的起始端为信号量发送方,箭头的末端为信号量的接收方。

3.2.2系统任务和资源分配

μC/OS-II是一个实时多任务操作系统,所以把系统软件分割成多个任务,每个任务负责完成部分工作,系统功能由多个任务协作完成。

任务分配方案的好坏将直接影响软件的编写的效率和性能。

本系统的任务分配如表1所示。

在起始任务中建立了一系列信号量来协调各个任务的执行,各信号量的作用如表2所示。

3.2.3主要任务描述

首先建立一个主函数(main函数),在主函数中调用OSInit()函数初始化μC/OS-II,然后建立第一个任务(起始任务),最后调用OSStart()函数启动多任务。

当然,在建立主函数之前必须定义各个任务的堆栈,系统的全局变量和相关宏。

主函数的程序清单如下:

起始任务(StartTask)是系统建立的第一个任务,他主要有3个功能:

完成对定时器、外中断0和串行口的初始化;

建立系统所要用到的信号量;

建立系统的其他任务。

起始任务部分程序清单如下:

电机开窗任务(openwintask)在电机开窗任务中首先等待信号量sem_open。

该信号量是由煤气处理任务、红外遥控处理任务和手动开窗任务发送的。

如果其他任务发送了该信号量,程序就设置电机转动方向,并控制p3.4送出电机转动脉冲,直到窗户被打开。

电机关窗任务(closewintask)该任务必须在信号量semopen有效时才会被激活。

信号量sere_open有下雨处理任务、红外遥控处理任务和手动关窗任务发送。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2