您好!欢迎来到信盈达产学合作协同育人平台|校企合作|嵌入式培训|解决方案|

登录 注册 微信快速登录

扫一扫看效果 关闭

好文章,欢迎分享给朋友

他有一片海

01-18 16:46    浏览2716

学习达到效果:

1)了解UCOS工作运行的原理;

2)了解UCOS的文件结构,能够自行阅读相关文件;

3)掌握UCOSAPI函数。多写,多练。

学习的主要文档:

1)UCOSII源码;

2)μCOS-II_2.92 API函数详解 v2.0

3)嵌入式实时操作系统μCOS-II原理及应用-任哲(高清版本)

第1章 操作系统的概念

1.1 操作系统的基本概念

操作系统的定义:操作系统(Operating SystemOS)介于硬件和软件之间,为开发者提供APIApplication Programming Interface函数接口,屏蔽硬件细节,提高开发效率。

操作系统的分类:实时操作系统(FreeRTOSUCOSRTXRT-Thread。)和分时操作系统(高版本的Linuxwindows)。

RTOSReal Time Operating System 。一般用于低端场合,芯片的主频较低。实时性:对于重要的事件能够及时响应,可能同时发生很多事情,虽然MCU不可能同时全部处理,但是他一定能够处理最重要的一件事。在工业产品中有很多应用。

UCOSUCOS的学习资料丰富。代码体系完善。

前后台系统:

裸机代码:前后台系统,一般将while(1)循环里面的程序称之为后台代码,将中断服务函数称之为前台代码。程序功能是通过在主函数当中调用一个个的子函数,并通过控制语句控制程序流向。

我们一般在中断服务函数修改标志位,在主函数判断标志位处理任务,但是这中间会有时间延时,称之为任务延时,当我们的主函数功能越来越多,判断条件越来越多,会导致操作时间越来越长,功能维护越来越困难。

操作系统:通过任务调度器对内核资源的管理(管理CPU的使用权),能够实现对多个任务的及时、并发性(每次还是只有一个任务运行,任务切换很快)的处理。

UCOS核心是任务程序功能是通过一个个任务去实现的。每个任务都一个while(1)死循环,没有退出条件没有返回值, 我们是通过在任务中调用系统提供的API实现任务和任务之间的转换。

1.2 UCOS操作系统

1.2.1 UCOS的源码体系结构

与处理器无关

os_core.c

系统核心文件

os_flag.c

任务通信:事件标志组底层文件

os_mbox.c

任务通信:消息邮箱

os_mem.c

内存管理:实现内存动态分配,以及释放功能类似标准C malloc free

os_mutex.c

任务通信:互斥锁支持

os_q.c  

任务通信:消息队列支持

os_task.c

任务管理

os_time.c

时间管理相关函数

os_tmr.c

软件定时器相关函数

与处理器有关

os_cpu_c.cos_cpu_a.s

移植时候需要修改的文件

os_cpu.h

cpu相关的头文件

ucos_ii.h

μC/OS中所有可用API函数声明文件

1.2.2 UCOS系统的特点

微型化:  代码量很少,最小可以是8K左右

专用性强:UCOS系统能够应用在很多低端芯片上,比如STM32

可裁剪:  我们在移植时,只需要在OS_CFG_H文件中将相应的宏开关关闭,就能裁剪掉我们不需要的代码程序,达到系统裁剪的目的。

实时性高:因为UCOS操作系统是抢占任务式操作系统,系统正在执行的任务一定是就绪的任务当中,任务优先级最高的。

第2章 UCOS任务

2.0.1 任务的概念

什么叫任务?在系统中,可以先简单的认为每个UCOS任务就是一个while(1)循环。

UCOS系统中,程序的流向不是由主函数决定的。而是由系统分配CPU使用权的。

裸机代码,没有跑操作系统,程序基本都是在while(1)循环里实现,同一时刻,只会执行一个while(1)循环,while(1)循环的切换一般用break实现。

跑系统,每个任务就是一个while(1)循环,可以多个while(1)循环并行执行(两个循环的切换非常快,延时很小。)

int main(void)

{

//各模块初始化

while(1)

{

//通过各个控制语句控制程序流向

}

}

int main(void)

{

//启动UCOS系统

}

void task1(void)

{

//这部分代码也会执行,但是只会在任务第一次执行时执行

while(1)

{

//只要任务还在运行,就会继续执行

}

}

void task2(void)

{

//这部分代码也会执行,但是只会在任务第一次执行时执行

while(1)

{

//只要任务还在运行,就会继续执行

}

}

2.0.2 任务状态

2.0.3 任务间关系

2.1 任务优先级

2.1.1 任务优先级

2.8.6版本之后的UCOS256个不同的优先级设置,优先级用数字表示0~255,数字越小优先级越高。系统已经默认将最低优先级255分配给空闲任务;如果使用了统计任务,系统还会将优先级254分配给统计任务。一般将软件定时器的优先级设定为最高0。(我们移植的ucos系统,只允许设置64层优先级,可以在配置文件修改。)

一般不建议将任务设置为最高的几个优先级,建议分配中间那部分的优先级。留出较高和较低方便拓展。

注意:每个任务对应一个优先级,一个优先级一定是只能对应一个任务。

2.1.2 空闲任务

由于任务总是在5种状态之间切换,所以系统极有可能在某一时刻没有任务可执行,但是停止CPU工作会导致一些莫名错误,所以系统创建了一个空闲任务,当系统中的其他任务都不执行时,系统就会运行空闲任务。

2.1.3 统计任务

统计任务统计CPU1秒钟内被其他任务占用的时间,并将结果保存在全局变量 OSCPUsage当中

2.2 任务调度

UCOS任务切换是通过任务调度器实现的,任务调度器的任务调度,只有在正在运行的任务放弃CPU使用权,或者发生任务抢占时才工作中断退出。

2.3 任务控制块

UCOS的任务控制块是用来记录任务的堆栈指针,当前状态,优先级等等与任务相关的信息,每个任务被创建时,UCOS都会分配给她一个空白的任务控制块用以存储该任务的相关信息。当一个任务被删除之后,他的任务控制块又可以重新使用。

任务控制块:TCBtask control block

该控制块的定义在ucosii.h文件的 530行。

第3章 新建UCOS工程

3.1 需要的资料

1) 一个已经完整的裸机代码

2) 相应的UCOS源文件官网下载micrum

3) os_cpu.hos_cpu_a.asmos_cpu_c.cos_cfg.hincludes.h

3.2 第一步

将相关文件添加到工程,根据编译提示,去除相应文件,并且到os_cfg.h文件修改宏开关量。

3.3 第二步

使用滴答定时器为系统生成时钟节拍,调用相关函数完成节拍统计。

3.4 第三步

初始化系统,建立任务,启动UCOS


第4章 UCOS系统初始化

4.1 系统节拍介绍

UCOS系统任务切换是以时间片为单位的,时间片即是UCOS系统的心跳、系统节拍。可以用滴答定时器实现,或者其他定时器,在相关的定时中断中调用系统关于节拍统计的相关函数。

时钟节拍数指的是系统一秒钟进入的定时器中断的次数。

假设系统节拍是200,那么请问滴答定时器多久产生一次滴答中断

答:每个节拍时间是5ms

OS_CFG_H文件中,定义了时钟节拍数,建议初始化节拍时调用该量。

假设函数SysTick_Init_ms(u16 ms);要实现一秒钟200个节拍。

SysTick_Init_ms(1000/OS_TICKS_PER_SEC);

一个节拍的时间越小:节拍数越多,CPU越忙,系统的实时性更高。

一个节拍的时间越大:节拍数越少,CPU越闲,系统的实时性较差。

一般建议一个节拍5~10ms。节拍数:200~100

滴答中断的优先级:应该配置为最低优先级。

4.2 系统节拍初始化代码

void SysTick_Init_xms(u32 ms)

{

SysTick->CTRL &=~(1<<0); //关闭滴答定时器

SysTick->CTRL &=~(1<<2); //选择时钟源为 21 MHz

SysTick->CTRL &=~(1<<1); //关闭滴答中断

SysTick->LOAD = 21000*ms;   //向自动重载寄存器写入计数值

SysTick->VAL =0;         //初始化当前值寄存器

SysTick->CTRL |=1<<1;    //打开滴答中断

NVIC_SetPriorityGrouping(5);             //分组设置  

NVIC_SetPriority(SysTick_IRQn,NVIC_EncodePriority(5,3,3) ); //优先级设置为最低

NVIC_EnableIRQ(SysTick_IRQn);             //中断通道使能

SysTick->CTRL |=1<<0;    //打开滴答定时器

}

void SysTick_Handler(void)

{

OSIntEnter();//通知内核中断函数正在执行。

if( SysTick->CTRL & (1<<16))

{

OSTimeTick();//节拍统计

}

OSIntExit(); //通知内核一个中断服务已执行完毕。

}

4.3 系统初始化

OSInit(); // 初始化 uC/OS-II

// 最少创建一个任务

OSStart(); //启动多任务内核。


第5章 时间管理函数

5.1 时钟节拍初始化

os_cfg.h 中有定义:#define OS_TICKS_PER_SEC 1000意思是把 1 秒分成 1000 份,则每份是 1ms , 则一个时钟节拍就是 1MS ,一秒有1000个时钟节拍。

在使用滴答定时器初始化时,则

SysTick_Init(1000/OS_TICKS_PER_SEC);//一秒的节拍数是200

修改时钟节拍数,只需要修改OS_TICKS_PER_SEC的值。

5.2 任务延时函数OSTimeDly()

作用: 任务延时函数(时钟节拍数)。 实际是上放弃 CPU使用权,休眠去了。

函数原型:

void OSTimeDly(INT32U ticks);

参数:

ticks: 为要延时的时钟节拍数。

OSTimeDly(100);   //延时100个节拍,500ms

注意:所有的任务当中都应该有放弃CPU使用权的操作或者命令,否则优先级低于此任务的其他任务就永远没有办法执行。

5.3 任务延时函数OSTimeDlyHMSM()

作用: 任务延时函数(时钟节拍数)

函数原型:

INT8U OSTimeDlyHMSM (INT8U hours,

INT8U minutes,

INT8U seconds,

INT16U ms);

参数:

hours: 为延时小时数,范围从 0-255

minutes: 为延时分钟数,范围从 0-59

seconds: 为延时秒数,范围从 0-59

ms: 为延时毫秒数,范围从 0-999。需要说明的是,延时操作函数都是以时钟节拍为为单位的。实

际的延时时间是时钟节拍的整数倍。

例如系统每次时钟节拍间隔是 10ms,如果设定延时为 5ms,将不产生任何延时操作,而设定延时 15ms,实际的延时是两个时钟节拍,也就是 20ms


第6章 任务管理

6.1 任务创建函数

作用:创建一个新任务。

函数原型:

INT8U OSTaskCreate(void (*task)(void *pd),

void *pdata,

OS_STK *ptos,

INT8U prio);

OSTaskCreate()建立一个新任务。任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立。中断处理程序中不能建立任务。 一个任务必须为无限循环结构,且不能有返回点。

参数:

task: 是指向任务代码的指针。

pdata:指向一个数据结构,该结构用来在建立任务时向任务传递参数。

ptos: 为指向任务堆栈栈顶的指针。

prio: 为任务的优先级。每个任务必须有一个唯一的优先级作为标识。数字越小,优先级越高。

栈顶栈底:

数组buff[64],最高地址&buff[63]

数据地址由高地址向低地址增长,

buff[63](栈顶)-> buff[0](栈底)

6.2 任务删除函数

6.2.1 直接删除

作用: 删除任务,不让再有机会调度,除非重新创建。

函数原型:

INT8U OSTaskDel(INT8U prio);

参数:

prio: 为指定要删除任务的优先级,也可以用参数 OS_PRIO_SELF 代替,此时,下一个优先级最高的就绪

任务将开始运行。

6.2.2 请求删除任务函数

作用: 请求一个任务删除其它任务或自身。

函数原型:

INT8U OSTaskDelReq(INT8U prio);

参数:

prio: 为要求删除任务的优先级。如果参数为 OS_PRIO_SELF,则表示调用函数的任务正在查询是否有来自

其他任务的删除请求。

返回值:

OSTaskDelReq()返回下列错误代码之一:

OS_ERR_NONE: 删除请求已任务记录。

OS_ERR_TASK_NOT_EXIST:指定的任务不存在。发送删除请求的任务可以等待此返回值看是否成功。

OS_ERR_TASK_IDLE: 尝试删除空闲任务,不允许。

OS_ERR_PRIO_INVALID: 指定任务的优先级比 OS_LOWEST_PRIO 高于或不指定 OS_PRIO_SELF

OS_ERR_TASK_DEL: 任务被分配到一互斥。

OS_ERR_TASK_DEL_REQ: 当前任务收到来自其他任务的删除请求。


第7章 任务间通信

7.1 任务间通信

在裸机代码当中,功能是通过各个函数实现的。

各个函数之间如何同步、通信:参数传递,地址传递,返回值,全局变量。

在操作系统当中,功能是通过各个任务实现的,任务没有退出条件。

任务间通信:任务没有调用关系:参数传递,地址传递(不方便),只在任务创建时可用;全局变量。

i=10i++; 假如中断当中对变量i执行操作i--。最后i=

1)假如已经获得了i的值,然后中断发生,中断退出时不再去提取i的值。

2)中断当中,i--,获取i的当前值。i=10i--i=9;

3)之前将i的值10,已经被保存到栈区,直接使用,最后i=11;

为了实现任务间的实时性,可靠的通信。我们引入事件的概念。

事件:实现任务间的通信、同步。

事件的类型:信号量、消息邮箱、消息队列、互斥型信号量、事件标志组。

7.1.1 什么是事件

任务间通信需要用到事件。

事件类型:信号量,消息邮箱,消息队列,互斥型信号量,事件标志组。

事件控制块:当我们创建一个事件的时候,UCOS就会创建一个相应的事件控制块,事件控制块用来存储事件的相关信息,本质是一个结构体。

typedef struct os_event {

   INT8U    OSEventType;                

   void    *OSEventPtr;                  

   INT16U   OSEventCnt;                  

   OS_PRIO  OSEventGrp;                    

   OS_PRIO  OSEventTbl[OS_EVENT_TBL_SIZE];

#if OS_EVENT_NAME_EN > 0u

   INT8U   *OSEventName;

#endif

} OS_EVENT;

7.2 信号量创建和使用

信号量:信号量用于对共享资源的访问。信号量标识了共享资源的有效可被访问数量,要获得共享资源的访问权,首先必须得到信号量这把钥匙。信号量本质是一个u16的整型变量,我们对信号量的操作,其实都是在对这个变量进行++或者--的操作或者赋值操作

我们使用信号量,只需要将它当作一个变量使用。(定义、++--,赋值)

作用:所有的你在裸机代码当中全局变量(u16)能完成的事情,都能完成。

7.2.1 创建信号量

作用: 建立并初始化一个信号量。

函数原型:

OS_EVENT *OSSemCreate(INT16U value);

参数:

value 参数是建立的信号量的初始值,可以取 0 65535 之间的任何值。

返回值:

OSSemCreate()函数返回指向分配给所建立的消息邮箱的事件控制块的指针。如果没有可用的事件控制块,

OSSemCreate()函数返回空指针。

7.2.2 发送信号量

作用: 发出一个信号量,把信号值加 1

函数原型:

INT8U OSSemPost(OS_EVENT *pevent);

OSSemPost()函数置起(把信号值加 1)指定的信号量。如果指定的信号量是零或大于零, OSSemPost()函数递

增该信号量并返回。如果有任何任务在等待信号量,最高优先级的任务将得到信号量并进入就绪状态,任务调度

函数将进行任务调度。

参数:

pevent: 指向信号量的指针。

7.2.3 无等待查看信息

作用: 无等待查看消息邮箱是否收到消息。

函数原型:

INT16U OSSemAccept(OS_EVENT *pevent);

OSSemAccept()函数查看设备是否就绪或事件是否发生。不同于 OSSemPend()函数,如果设备没有就绪,

OSSemAccept()函数并不挂起任务。中断调用该函数来查询信号量。

参数:

pevent: 是指向需要查询的设备的信号量。当建立信号量时,该指针返回到用户程序。(参考 OSSemCreate

()函数)。

返回值:

当调用 OSSemAccept()函数时,设备信号量的值大于零,说明设备就绪,这个值被返回调用者,设备信号量的值减一。如果调用 OSSemAccept()函数时,设备信号量的值等于零,说明设备没有就绪,返回零。

7.2.4 挂起任务等待信号量

作用: 申请一个信号量(挂起任务等待信号量)。

函数原型:

void OSSemPend (OS_EVENT *pevent,

INT32U timeout,

INT8U *perr);

OSSemPend()函数用于任务试图取得设备的使用权,任务需要和其他任务或中断同步,任务需要等待特定事

件的发生的场合。 如果任务调用 OSSemPend()函数时,信号量的值大于零, OSSemPend()函数递减该值。 如果调用时信号量等于零, OSSemPend()函数函数将任务加入该信号量的等待队列。

参数:

pevent: 指向消息邮箱的指针。

timeout: 任务等待超时周期, 为 0 时表示无限等待; 其它, 递减到 0 时任务恢复执行。

perr: 做为输出参数使用, 指向错误代码变量的指针。

7.2.5 设置信号量的值OSSemSet()

作用: 改变当前信号量的计数值。 当信号量被用于表示某事件发生了多少次的情况下会使用。
函数原型:
void OSSemSet(OS_EVENT *pevent,
           INT16U cnt,
           INT8U *perr);

参数:
pevent: 指向信号量的指针。
cnt: 期望的数值。
perr: 指向错误代码变量的指针,其返回值如下:
OS_ERR_NONE 计数值改变成功。
OS_ERR_EVENT_TYPE pevent 不是一个指向信号量的指针。
OS_ERR_PEVENT_NULL pevent 传入的是一个空指针。
OS_ERR_TASK_WAITING 存放任务在等待信号量。
返回值: 无。
注意:
1. 必须先建立信号量,然后使用。
2. 当有其他任务使用OSSemPend 函数等待此信号量时,不能在信号量的值为0时调用此函数OSSemSet否则会返回错误代码OS_ERR_TASK_WAITING 存放任务在等待信号量。

7.3
消息邮箱

7.4 消息邮箱

7.4.1 建立消息邮箱

作用: 建立并初始化一个消息邮箱。

函数原型:

OS_EVENT *OSMboxCreate (void *pmsg);

参数:

msg: 参数用来初始化建立的消息邮箱。如果该指针不为空, 则建立的消息邮箱将含有消息。

返回值:

指向分配给所建立的消息邮箱的事件控制块的指针。如果没有可用的事件控制块,返回空指针。

7.4.2 发送消息

作用: 向邮箱发送一则消息。

函数原型:

INT8U OSMboxPost (OS_EVENT *pevent,void *pmsg);

OSMboxPost()函数通过消息邮箱向任务发送消息。消息是一个指针长度的变量,在不同的程序中消息的使用

也可能不同。如果消息邮箱中已经存在消息,返回错误码说明消息邮箱已满OSMboxPost()函数立即返回调用者,

消息也没有能够发到消息邮箱。 如果有任何任务在等待消息邮箱的消息,最高优先级的任务将得到这个消息。 如

果等待消息的任务优先级比发送消息的任务优先级高,那么高优先级的任务将得到消息而恢复执行,也就是说,

发生了一次任务切换。

参数:

pevent: 指向消息邮箱的指针。

pmsg: 是即将发送给任务的消息。消息是一个指针长度的变量,在不同的程序中消息的使用也可能不同。不允许传递一个空指针。

7.4.3 获取消息

作用: 无等待查看消息邮箱是否收到消息。

函数原型:

void *OSMboxAccept(OS_EVENT *pevent);

OSMboxAccept()函数查看指定的消息邮箱是否有需要的消息。不同于 OSMboxPend()函数,如果没有需要的消息,OSMboxAccept()函数并不挂起任务。如果消息已经到达,该消息被传递到用户任务并且从消息邮箱中清除。通常中断调用该函数,因为中断不允许挂起等待消息。

参数:

pevent: 是指向需要查看的消息邮箱的指针。当建立消息邮箱时,该指针返回到用户程序。(参考

OSMboxCreate()函数)。

返回值:

如果消息已经到达,返回指向该消息的指针;

7.5 作业

用消息邮箱实现将触摸屏得到的LCD坐标的值通过串口打印出来,要求用两个任务完成。

注意:要使用触摸屏,需要进行相应的初始化。


7.6 消息队列

消息队列其实就是多个消息邮箱的组合,消息邮箱一般用在发送方发送较慢,接收方处理消息较快的时候;

消息队列多用在发送方发送消息较快,接收方处理消息较慢的时候。

7.6.1 创建消息队列

作用: 建立并初始化一个消息队列。

函数原型:

OS_EVENT *OSQCreate (void **start,INT16U size)

OSQCreate()函数建立一个消息队列。任务或中断可以通过消息队列向其他一个或多个任务发送消息。消息

的含义是和具体的应用密切相关的。

参数:

start: 是消息内存区的基地址,消息内存区是一个指针数组。

size: 是消息内存区的大小。

7.6.2 按规则发送消息FIFO

作用: 向邮箱发送一则消息(FIFO)

函数原型:

INT8U OSQPost (OS_EVENT *pevent,void *pmsg);

OSQPost()函数通过消息队列向任务发送消息。消息是一个指针长度的变量,在不同的程序中消息的使用也

可能不同。 如果队列中已经存满消息,返回错误码;OSQPost()函数立即返回调用者,消息也没有能够发到队列。

如果有任何任务在等待队列中的消息,最高优先级的任务将得到这个消息。 如果等待消息的任务优先级比发送消息的任务优先级高,那么高优先级的任务将得到消息而恢复执行,也就是说,发生了一次任务切换。 消息队列是先入先出(FIFO)机制的,先进入队列的消息先被传递给任务。

参数:

pevent: 指向消息队列的指针。

pmsg: 是即将发送给任务的消息。消息是一个指针长度的变量,在不同的程序中消息的使用也可能不同。

不允许传递一个空指针。

7.6.3 发送LIFO消息

作用: 向邮箱发送一则消息(LIFO)

函数原型:

INT8U OSQPostFront (OS_EVENT *pevent,void *pmsg);

OSQPostFront()函数通过消息队列向任务发送消息。 OSQPostFront()函数和 OSQPost()函数非常相似,

不同之处在于 OSQPostFront()函数将发送的消息插到消息队列的最前端。也就是说,OSQPostFront()函数使得消息队列按照后入先出(LIFO)的方式工作,而不是先入先出(FIFO)。 如果队列中已经存满消息,返回错误码。 OSQPost()函数立即返回调用者,消息也没能发到队列。如果有任何任务在等待队列中的消息,最高优先级的任务将得到这个消息。如果等待消息的任务优先级比发送消息的任务优先级高,那么高优先级的任务将得到消息而恢复执行,也就是说,发生了一次任务切换。

7.6.4 查看消息队列

作用: 无等待查看消息队列是否收到消息。

函数原型:

void *OSQAccept (OS_EVENT *pevent,INT8U *perr);

OSQAccept()函数检查消息队列中是否已经有需要的消息。不同于 OSQPend()函数,如果没有需要的消息,

OSQAccept()函数并不挂起任务。如果消息已经到达,该消息被传递到用户任务。通常中断调用该函数,因为中

断不允许挂起等待消息。

参数:

pevent: 是指向需要查看的消息队列的指针。当建立消息邮箱时,该指针返回到用户程序。(参考 OSQCreate ()

函数)。

perr: 指向一个用于保存错误代码的变量。


7.7 互斥型信号量

7.7.1 创建互斥信号量

作用: 建立并初始化一个互斥型信号量。

函数原型:

OS_EVENT *OSMutexCreate (INT8U prio,INT8U *perr);

参数:

prio: 较高的空闲优先级,用于任务提权。

perr: 指向一个用于保存错误代码的变量。

7.7.2 申请互斥信号量

作用: 无等待请求互斥型信号量。

函数原型:

BOOLEAN OSMutexAccept (OS_EVENT *pevent,INT8U *perr);

参数:

pevent: 指向要请求的互斥信号量的指针。

perr: 指向一个用于保存错误代码的变量。

7.7.3 释放互斥信号量

作用: 释放一个互斥型信号量。

函数原型:

INT8U OSMutexPost (OS_EVENT *pevent);

参数:

pevent: 指向一个互斥型信号量的指针。

7.8 软件定时器

7.8.1 创建软件定时器

作用: 创建软件定时器。

函数原型:

OS_TMR *OSTmrCreate(INT32U dly,

INT32U period,

INT8U opt,

OS_TMR_CALLBACK callback,

void *callback_arg,

INT8U *pname,

INT8U *perr);

参数:

dly 指定使用的计时器初始延迟时间。

l 在单次触发模式时,这是单次定时的时间。

l 在周期模式下,这是最初定时器进入周期模式之前的延时。

l 延时单位取决于你多久调用一次 OSTmrSignal()。如果 OS_TMR_CFG_TICKS_PER_SEC 设置为

10,则 DLY 指定延迟时间为 1/10 秒(也就是 100ms)。 OS_TMR_CFG_TICKS_PER_SEC 设置为多

少,就是 1/OS_TMR_CFG_TICKS_PER_SEC 秒。 需要注意的是在创建时的定时器不能启动。

period 指定计时器周期性定时的时间量。 如果设置为 0,那么将使用单次模式。

opt

OS_TMR_OPT_PERIODIC:指定周期性定时模式。

OS_TMR_OPT_ONE_SHOT:指定单次定时模式。

请注意,必须选择其中一个选项。

callback

n 指定一个回调函数的地址(可选),这个函数将被调用,处理定时结束的相关事项,回调函数必须

声明如下:

void MyCallback (void *ptmr, void *callback_arg);

n 如果不需要回调函数,可以传入一个空指针。

callback_arg 是传递给回调函数参数,如果回调函数不需要参数,可以是一个空指针。

pname : 指向一个 ASCII 字符串,用于设置定时器名称。通过调用 ostmrnameget()获取这个名称。

perr 指向存放错误代码的指针,

7.8.2 启动软件定时器

作用: 启动计时器。

函数原型:

BOOLEAN OSTmrStart(OS_TMR *ptmr,INT8U *perr);

参数:

ptmr: 指向想要启动的定时器。该指针的值为在创建定时器时返回的值(见 OSTmrCreate())。

perr: 指向存放错误代码的变量。

7.9 临界宏

OS_CPU_SR cpu_sr;

OS_ENTER_CRITICAL();

//核心代码

OS_EXIT_CRITICAL();

7.10 作业


评论0 0
评论
内容加载中……,请稍候!

手指长按二维码,快速关注

给TA留言
留言
返回
评论