微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > STM32 uCOS_II 实践 之 事件标识组

STM32 uCOS_II 实践 之 事件标识组

时间:12-03 来源:互联网 点击:
在中断的那一章节里介绍了计数信号量,它可以有效的传递一个二值信号,而时间标识组是多个信号量运算后作用与一个任务的工具。主要应用场合是两个以上的任务来同步一个任务。

在这里ucos的运行过程应该都有一定的了解了,对信号量传递的过程可以查看另外一个帖子,这里只关注事件标识组本身。

首先运用事件标识组需要四个步骤:

  1. 声明一个标识组指针变量,

    void *SemGrp_Task_LED1;

    这个里面存放的是事件控制块的指针,并且是一个全局的变量,需要在对应的头文件里进行全局声明(extern),在对标识组进行初始化的时候,也就是对事件控制块的初始化,事件控制块是管理和调配这个资源的模块;
  2. 初始化事件标识组,

    SemGrp_Task_LED1 = OSFlagCreate(0,&err);

    参数0为最终逻辑运算的结果初始值为0,参数&err为错误信息;
  3. 在用户任务里设置等待函数,

    OSFlagPend( SemGrp_Task_LED1, // 标识组指针
    0x03, // 标识为后两位
    OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME,// 设置与操作并且操作后清除标识
    0,&err // 无等待超时
    );

    总共有5个参数,第一个参数设置标识组指针,说明等待的是哪个标识组;第二个参数是标识组里有哪些操作位,0x03就是说明有2个信号量参与这个组并且是一个字节的最低两位;第三个参数是这些信号量由哪种组合方式来形成一个有效的信息,就两种操作“与”和“或”,即所有单个信号量都为1时才触发或者是只要有一个信号量发送1就触发,对应的还有一个操作关系就是在操作后对单个信号量进行清零;第四个参数是等待时间,单位是系统心跳数,0就是指无时间限制的等待;第五个参数是错误类型。
  4. 在不同的用户任务里或者触发任务里设置发送信号量函数,

    OSFlagPost(SemGrp_Task_LED1,0x01,OS_FLAG_SET,&err);// 置位组标志位的第一位

    总共有四个参数,第一个参数为标识组指针,说明你是发到哪个标识组里的;第二个参数说明你操作的是第几位,在等待函数里设置了具体的有效位,在发送函数里说明你发送的这一位是等待函数里的第几位,代码例子里是发送的最低位;第三个参数是设置置一还是清零,OS_FLAG_SET为置一,OS_FLAG_CLR为清零;第四个参数是错误类型。
=====================================================================================
下面是在系统内部实际的代码:
步骤2及步骤3

void Task_LED1(void* p_arg)
{
(void) p_arg ;

SemGrp_Task_LED1 = OSFlagCreate(0,&err);
while(1)
{
OSFlagPend( SemGrp_Task_LED1, // 标识组指针
0x03, // 标识为后两位
OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME, // 设置与操作并且操作后清除标识
0,&err // 无等待超时
);

LED1_HIGH;
OSTimeDlyHMSM(0,0,1,0);
LED1_LOW;
OSTimeDlyHMSM(0,0,1,0); // 延时,用来给其他任务留有运行的时间
}
}

两个 步骤4函数,分别在外部中断服务函数里:

void Interrupt_Handle_KEY2(void)
{
OSIntEnter();

// 在中断服务函数里如果调用ucos系统函数的话就必须加上进中断系统函数出去的时候要加上出中断系统函数

OSFlagPost(SemGrp_Task_LED1,0x01,OS_FLAG_SET,&err); // 置位组标志位的第一位
EXTI_ClearITPendingBit(EXTI_Line4); // 清除标志位

OSIntExit();
}

void Interrupt_Handle_KEY3(void)
{
OSIntEnter();

// 在中断服务函数里如果调用ucos系统函数的话就必须加上进中断系统函数出去的时候要加上出中断系统函数

OSFlagPost(SemGrp_Task_LED1,0x02,OS_FLAG_SET,&err); // 置位组标志位的第二位
EXTI_ClearITPendingBit(EXTI_Line3); // 清除标志位

OSIntExit();
}

总结:
对于事件标识组的操作,思路是非常简单的,在一个最终结果的任务里添加等待函数,系统运行到这里会把这个任务挂起,然后按照逻辑去等待各个单一的信号量,在其他的任务里有发送函数,按照等待函数里设定好的操作位去把各个位去置高或者拉低,就能达到多个任务去同步一个任务的目的。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top