} }
程序中每个任务获得互斥锁后打印字符串,并延时1s钟后解锁,这样下个任务才能进行上锁,完成自己的任务。其程序从串口打印如下
实验六、邮箱
本节我们主要介绍的是uC/OS-II的邮箱 1、邮箱介绍
μC/OS-II中的邮箱也称为消息邮箱, 是用一个指针型变量, 通过内核服务, 一个任务或一个中断服务程序可以把一则消息(即一个指针)放到邮箱里去。同样,一个或多个任务可以通过内核服务接收这则消息。发送消息的任务和接收消息的任务约定,该指针指向的内容就是那则消息。消息邮箱与消息队列类似,消息邮箱相当于消息队列的一个成员,消息队列实际上是邮箱阵列。如下图是任务、中断服务子程序和邮箱之间的关系。
2、邮箱操作
μC/OS-II提供了一系列函数对邮箱进行创建、获取和给出等。 1)创建邮箱OSMboxCreate()
OS_EVENT *OSMboxCreate (void *msg)
msg 邮箱的初始指针为0则无初值 返回值 NULL创建失败 否则返回事件控制块指针
2)信号量获取OSSemPend( )等待和OSMboxAccept()立即返回 void *OSMboxPend (OS_EVENT *pevent,INT16Utimeout, INT8U*err) void *OSMboxAccept (OS_EVENT *pevent)
pevent 创建邮箱时返回的指针 Timeout 阻塞超时时间。 err 错误类型 返回值 NULL获取失败 邮件指针
3)发出邮箱OSMboxPost()
INT8U OSMboxPost (OS_EVENT *pevent,void *msg) pevent 创建邮箱时返回的指针 msg 要发送的邮箱指针 返回值 有两个可能的返回值: 1.OS_NO_ERR 清空成功 2.OS_ERR_EVENT_TYPE 事件类型错误 3.OS_MBOX_FULL 邮箱满 3)查询一个信号量的当前状态OSMboxQuery()
INT8U OSMboxQuery (OS_EVENT*pevent, OS_MBOX_DATA *pdata) pevent 创建邮箱时返回的指针
pdata 用于记录邮箱信息的数据结构 返回值 有两个可能的返回值: 1.OS_NO_ERR 清空成功 2.OS_ERR_EVENT_TYPE 事件类型错误 3、实验分析
实验创建两个任务,任务二每隔500ms发送发送一次邮箱,并打印发送状态,任务一则一直阻塞等待接收邮箱,并打印接受到的邮箱。其实验代码如下: int main (void) {
INT8U err;
SysTick_Configuration(); //系统定时器初始化 USART_Configuration(); //串口初始化 LED_Configuration();
OSInit(); //usos ii初始化
CommMbox = OSMboxCreate((void *)0); //建立消息邮箱 AppTaskCreate();//创建任务
OSStart(); //开始任务调度 }
static void AppTaskCreate(void) {
INT8U err;
OSTaskCreateExt(AppTask1,(void*)0,(OS_STK )&AppTask1Stk[APP_TASK1_STK_SIZE-1],APP_TASK1_PRIO,APP_TASK1_PRIO,(OS_STK)&AppTask1Stk[0],APP_TASK1_STK_SIZE,(void )0,OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); //创建任务1
OSTaskNameSet(APP_TASK1_PRIO, \&err);
OSTaskCreateExt(AppTask2,(void*)0,(OS_STK )&AppTask2Stk[APP_TASK2_STK_SIZE-1],APP_TASK2_PRIO,APP_TASK2_PRIO,(OS_STK )&AppTask2Stk[0],APP_TASK2_STK_SIZE,(void*)0,OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); //创建任务2
OSTaskNameSet(APP_TASK2_PRIO, \&err); }
//邮箱接收任务
static void AppTask1 (void *p_arg) {
INT8U err; void *msg; while(1) {
msg=OSMboxPend(CommMbox,600,&err);//等待接收邮箱最大时间600ms if (err == OS_NO_ERR){
printf(\接收到消息%s\\r\\n\*)msg);//消息正确的接受 } else{
printf(\没有接收到消息\\r\\n\//在指定时间内没有接受到消息 } } }
//邮箱发送任务
static void AppTask2 (void *p_arg) {
INT8U CommRxBuf[100]=\INT8U err; while(1) {
err= OSMboxPost(CommMbox, (void *)CommRxBuf); if (err == OS_NO_ERR){
printf(\发送成功\\r\\n\//发送成功 } else{
printf(\发送失败\\r\\n\//发送失败 }
OSTimeDlyHMSM(0,0,0,500); }
}
本程序为ucos的另一种通信方式邮箱,工程创建两个任务,一个每隔500ms发送一个邮箱,一个等待接收邮箱最大等待时间600ms,任务二发送邮箱并打印“发送成功”,任务一接收到邮箱后打印“接收到消息bbs.openmcu.com”。
实验七、事件标志组
本节我们主要介绍的是uC/OS-II的事件标志组 1、事件标志组介绍
μC/OS-II中当某任务要与多个事件同步时,要使用事件标志。若任务需要与任何事件之一发生同步,可称为独立型同步(即逻辑或关系)。任务也可以与若干事件都发生了同步,称之为关联型(逻辑与关系)。独立型及关联型同步如图所示。
2、事件标志组操作
μC/OS-II提供了一系列函数对邮箱进行创建、获取和给出等。 1)创建事件标志组OSFlagCreate ()
OS_FLAG_GRP *OSFlagCreate (OS_FLAGS flags, INT8U *perr) flags 事件标志组初始化值 Perr 错误标志 返回值 标志组指针 2)等待标志置位获取OSFlagPend ()
OS_FLAGS OSFlagPend (OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT16U timeout, INT8U *perr)
pgrp 标志组指针 flags 等待标志位
wait_type 设置操作类型‘与’‘或’
Timeout 等待事件 Perr 错误类型 3)发出邮箱OSFlagPost()
OS_FLAGS OSFlagPost (OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U opt, INT8U *perr)
pgrp 标志组指针 flags 等待标志位
opt 置位还是清零 Perr 错误类型 3、实验分析
实验创建三个任务,任务一等待事件标志组bit0和bit1置位,任务二置位标志组bit1位,任务三置位标志组bit0位。其实验代码如下: int main (void) {
SysTick_Configuration(); //系统定时器初始化 USART_Configuration(); //串口初始化 LED_Configuration();
OSInit(); //usos ii初始化
Sem_F=OSFlagCreate(0,&err);
OSFlagPost(Sem_F,(OS_FLAGS)0,OS_FLAG_CLR,&err); AppTaskCreate();//创建任务
OSStart(); //开始任务调度
}
static void AppTaskCreate(void) {
INT8U err;
OSTaskCreateExt(AppTask1,(void*)0,(OS_STK )&AppTask1Stk[APP_TASK1_STK_SIZE-1],APP_TASK1_PRIO,APP_TASK1_PRIO,(OS_STK)&AppTask1Stk[0],APP_TASK1_STK_SIZE,(void )0,OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); //创建任务1
OSTaskNameSet(APP_TASK1_PRIO, \&err);
OSTaskCreateExt(AppTask2,(void*)0,(OS_STK )&AppTask2Stk[APP_TASK2_STK_SIZE-1],APP_TASK2_PRIO,APP_TASK2_PRIO,(OS_STK )&AppTask2Stk[0],APP_TASK2_STK_SIZE,(void*)0,OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); //创建任务2
OSTaskNameSet(APP_TASK2_PRIO, \&err);
OSTaskCreateExt(AppTask3,(void*)0,(OS_STK )&AppTask3Stk[APP_TASK3_STK_SIZE-1],APP_TASK3_PRIO,APP_TASK3_PRIO,(OS_STK )&AppTask3Stk[0],APP_TASK3_STK_SIZE,(void*)0,OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); //创建任务3
OSTaskNameSet(APP_TASK2_PRIO, \&err); }
//任务1
static void AppTask1 (void *p_arg)