µCOS-III从入门到精通 第十三章(事件标志组)

参考教程:【正点原子】手把手教你学UCOS-III实时操作系统_哔哩哔哩_bilibili

一、事件标志组简介

1、概述

(1)事件标志位是一个“位”,用来表示事件是否发生。

(2)事件标志组是一组事件标志位的集合,可以简单的理解事件标志组,是一个整数。

(3)事件标志组的特点:

①每一个位与一个事件相关联,高8位除外,高8位用作存储事件标志组的控制信息。(下图所示的是32 位长度的事件标志组)

②每一位事件的含义,以及高电平和低电平分别代表什么,由用户自己决定。

③任意任务或中断都可以写这些位,但读这些位只能由任务来读。

④可以等待某一位成立,或者等待多位同时成立。

⑤支持读取阻塞。

2、事件标志组相关API函数介绍

(1)事件标志组相关API函数概览:

函数

描述

OSFlagCreate

创建一个事件标志组

OSFlagDel

删除一个事件标志组

OSFlagPend

等待事件标志组中的事件

OSFlagPendAbort

终止挂起等待事件标志组中的事件

OSFlagPendGetFlagRdy

获取任务等待到的事件

OSFlagPost

设置事件标志组中的事件

(2)OSFlagCreate函数:

void  OSFlagCreate
(
    OS_FLAG_GRP*	p_grp,                   
	CPU_CHAR*		p_name,                    
	OS_FLAGS   	    flags,                    
	OS_ERR*		    p_err
)

形参

描述

p_grp 

指向事件标志组结构体的指针

p_name 

指向作为事件标志组名的 ASCII 字符串的指针

flags 

事件标志组的初始值

p_err 

指向接收错误代码变量的指针

(3)OSFlagPost函数:

OS_FLAGS OSFlagPost   //返回事件标志组更新后的事件标志值
(
    OS_FLAG_GRP*	p_grp,                      
	OS_FLAGS     	flags,                      
	OS_OPT      	opt,                      
	OS_ERR*		    p_err
)

形参

描述

p_grp 

指向事件标志组结构体的指针

flags 

设置事件指定位清0或置1

opt 

函数操作选项:OS_OPT_POST_FLAG_SET 或 OS_OPT_POST_FLAG_CLR

p_err 

指向接收错误代码变量的指针

(4)OSFlagPend函数:

OS_FLAGS OSFlagPend //返回任务实际等待到的事件标志,如无任何标志准备就绪则为0
(
    OS_FLAG_GRP* 	p_grp,
	OS_FLAGS 		flags,
	OS_TICK 		timeout,
	OS_OPT 		    opt,
	CPU_TS* 		p_ts,
	OS_ERR* 		p_err
) 

形参

描述

p_grp 

指向事件标志组结构体的指针

flags 

等待的事件标志

timeout 

任务挂起等待事件标志的最大允许时间

opt 

函数操作选项

p_ts 

指向接收等待到事件时的时间戳的变量的指针

p_err 

指向接收错误代码变量的指针

        其中可选的函数操作选项如下所示:

opt

描述

OS_OPT_PEND_FLAG_CLR_ALL

等待“flags”中的所有指定位被清0

OS_OPT_PEND_FLAG_CLR_ANY

等待“flags”中的任意指定位被清0

OS_OPT_PEND_FLAG_SET_ALL

等待“flags”中的所有指定位被置1

OS_OPT_PEND_FLAG_SET_ANY

等待“flags”中的任意指定位被置1

调用上面四个选项的时候还可以搭配下面三个选项

OS_OPT_PEND_FLAG_CONSUME

当等待到指定位后,清0对应位

OS_OPT_PEND_BLOCKING

标志组不满足条件时挂起任务

OS_OPT_PEND_NON_BLOCKING

标志组不满足条件时不挂起任务

二、事件标志组实验

1、原理图与实验目标

(1)原理图(按键未画出,接法与任务信号量实验相同):

(2)①设计3个任务——start_task、task1、task2:

[1]start_task:用于创建其它三个任务,并创建事件标志组。

[2]task1:读取按键按下键值,根据不同键值将事件标志组相应事件位置1,模拟事件发生(按下某个按键,对应的标志位置1)。

[3]task2:同时等待事件标志组中的多个事件位,当这些事件位都置1的话就执行相应的处理(串口打印信息),同时清除标志位。

②预期实验现象:

[1]程序下载到板子上后,暂时没有任何现象。

[2]按下相关按键,串口会输出相应的信息。

2、实验步骤

(1)将“任务队列实验”的工程文件夹复制一份,在拷贝版中进行实验。

(2)更改UCOS_experiment.c文件的内容,如下所示。

#include "stm32f10x.h"                  // Device header
#include "os.h"
#include "cpu.h"
#include "Key.h"
#include "Serial.h"
#include <stdio.h>

/* START_TASK 任务 配置
 * 包括: 任务优先级 任务栈大小 任务控制块 任务栈 任务函数
 */
#define     START_TASK_PRIO         1
#define     START_TASK_STACK_SIZE  256
CPU_STK     start_task_stack[START_TASK_STACK_SIZE];
OS_TCB      start_task_tcb;
void start_task(void);

/* TASK1 任务 配置
 * 包括: 任务优先级 任务栈大小 任务控制块 任务栈 任务函数
 */
#define     TASK1_PRIO              4
#define     TASK1_STACK_SIZE       256
CPU_STK     task1_stack[TASK1_STACK_SIZE];
OS_TCB      task1_tcb;
void task1(void);

/* TASK2 任务 配置
 * 包括: 任务优先级 任务栈大小 任务控制块 任务栈 任务函数
 */
#define     TASK2_PRIO              3
#define     TASK2_STACK_SIZE       256
CPU_STK     task2_stack[TASK2_STACK_SIZE];
OS_TCB      task2_tcb;
void task2(void);

OS_FLAG_GRP flag;
#define FLAG_BIT0    (1 << 0)    //flag事件标志组bit0位置1时使用
#define FLAG_BIT1    (1 << 1)    //flag事件标志组bit1位置1时使用

void UCOS_Test(void)
{
	OS_ERR err;
	
	OSInit(&err);    //初始化μC/OS-III

	//创建Start Task
    OSTaskCreate (&start_task_tcb,
                  "start_task",
                  (OS_TASK_PTR)start_task,
                  NULL,
                  START_TASK_PRIO,
                  start_task_stack,
                  START_TASK_STACK_SIZE / 10,
                  START_TASK_STACK_SIZE,
                  0,
                  0,
                  0,
                  (OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                  &err);
    
    /* 开始任务调度 */
    OSStart(&err);
}

void start_task(void)              
{
    OS_ERR err;     //接收错误代码使用,对错误代码进行分情况处理可增强程序鲁棒性
    CPU_Init();     //初始化CPU库
    CPU_SR_ALLOC();
	
    OSFlagCreate (&flag, "flag", 0, &err);  //创建一个事件标志组
    
	//滴答定时器重装载值 = 系统主频 / 滴答定时器中断频率(滴答定时器是递减计数)
    CPU_INT32U cnts = SystemCoreClock / OS_CFG_TICK_RATE_HZ;
    OS_CPU_SysTickInit(cnts);   //配置Systick中断及优先级
    
    CPU_CRITICAL_ENTER();           //进入临界区(关中断)
	
    //创建task1
    OSTaskCreate (&task1_tcb,
                  "task1",
                  (OS_TASK_PTR)task1,
                  0,
                  TASK1_PRIO,
                  task1_stack,
                  TASK1_STACK_SIZE / 10,
                  TASK1_STACK_SIZE,
                  0,
                  0,
                  0,
                  (OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                  &err);

    //创建task2
    OSTaskCreate (&task2_tcb,
                  "task2",
                  (OS_TASK_PTR)task2,
                  0,
                  TASK2_PRIO,
                  task2_stack,
                  TASK2_STACK_SIZE / 10,
                  TASK2_STACK_SIZE,
                  0,
                  0,
                  0,
                  (OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                  &err);      
    
    CPU_CRITICAL_EXIT();            //退出临界区(开中断)
    OSTaskDel(NULL, &err);   //删除任务自身
}

void task1(void)
{
	OS_ERR err;
	uint8_t key = 0;
	while(1)
	{
		key = Key_GetNum();
        if(key == 1)
        {
            Serial_Printf("KEY1按下,bit0置1!!\r\n");
            OSFlagPost(&flag, FLAG_BIT0, OS_OPT_POST_FLAG_SET, &err);
        }
		else if(key == 2)
        {
            Serial_Printf("KEY2按下,bit1置1!!\r\n");
            OSFlagPost(&flag, FLAG_BIT1, OS_OPT_POST_FLAG_SET, &err);
        }
        OSTimeDly(10,OS_OPT_TIME_DLY,&err);
	}
}

void task2(void)
{
	OS_ERR err;
    while(1)
    {
        OSFlagPend(&flag,                     //事件标志组地址
                   FLAG_BIT0 | FLAG_BIT1,   //等待事件标志组的bit0和bit1位均置1
                   0,       
                   OS_OPT_PEND_FLAG_SET_ALL | OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_BLOCKING,
				   //等待“flags”中的所有指定位被置1
				   //等待到事件标志位后,清除事件标志组的bit0和bit1位
				   //标志组不满足条件时挂起任务
                   NULL,
                   &err);
        Serial_Printf("等待到指定事件成立!!!\r\n");
    }
}

(3)程序完善好后点击“编译”,然后将程序下载到开发板上,打开串口助手分析信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zevalin爱灰灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值