• 【FreeRTOS】10 事件标志组


    本节我们来讲讲freeRTOS的事件标志组。它也是一种用于任务间通信和同步的机制,和信号量有一些相似的功能,但也有自己的特点。

    1)什么是事件标志组

    一个事件标志组有多个事件位,每个事件位表示了一个事件的标志。

    比如我们用事件标志组的bit0表示事件A、bit1表示事件B、bit2表示事件C,那么这个事件标志组至少可以表示3个事件是否发生。

    之前我们讲过信号量,它用作信号同步时,只能表示一个资源的有无;而事件标志组,它可以同时表示多个资源的有无。

    上述的例子,相当于这个事件标志组实现了等效于3个二值信号量的功能,任务可以在一个事件标志组上同时等待A、B、C三个事件。

    任务在等待事件标志组的事件时,可以选等待该组中的一个或某几个事件位。比如上述例子中,虽然事件标志组表示了A、B、C三个事件,但是用户可以设置为只等待A和B。

    此外,事件标志组与信号量不同的另一点,是它可以选择在等待到某个事件位时是否对该事件位清零。而使用信号量时,获取到一个信号量时,信号量的计数会自动减1。

    2)FreeRTOS的事件标志组

    freeRTOS提供的事件标志组,由数据类型EventGroupHandle_t定义。使用前需要确认FreeRTOSConfig.h文件中configUSE_16_BIT_TICKS这个宏的定义,如果定义为1,则一个事件标志组可以最多存储8个事件位,如果定义位0,则可以存储24个事件位。

    下面讲解一下freeRTOS中操作事件标志组常用的一些函数。

    创建事件标志组:

    EventGroupHandle_t xEventGroupCreate( void );//创建一个事件标志组,返回的是创建成功的事件标准组句柄

    这个函数实际上是动态创建的事件标志组,如果想使用静态创建,需要用xEventGroupCreateStatic()函数。

    设置事件位:

    最主要是xEventGroupSetBits()、xEventGroupClearBits()两个函数,作用是把事件位置1或清0。函数原型为:

    EventBits_t xEventGroupClearBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear); //清0事件标志组,xEventGroup为要操作的事件标准组句柄,uxBitsToClear为要清的事件位,可以同时清多个位

    EventBits_t xEventGroupSetBits(EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); //设置事件标志组指定位为1,xEventGroup为要操作的事件标准组句柄,uxBitsToClear为要置1的事件位

    上述两个函数只能用在任务中,如果要在中断中设置事件标志组,要使用后缀为ISR的一套函数:xEventGroupSetBitsFromISR()和xEventGroupClearBitsFromISR()。

    等待事件位:

    EventBits_t xEventGroupWaitBits(

    EventGroupHandle_t xEventGroup,  /*要等待的事件标志组*/

    const EventBits_t uxBitsToWaitFor, /*要等待的事件位*/

    const BaseType_t xClearOnExit,  /*所等待的事件位是否清零,pdTRUE为清零,pdFALSE不变*/

    const BaseType_t xWaitForAllBits,  /*是否等待所有位,pdTRUE为等待uxBitsToWaitFor指定的所有位,pfFALSE只要uxBitsToWaitFor指定的其中一位置1就返回 */

    const TickType_t xTicksToWait );  /*等待超时时间*/

    获取事件标志组的值:

    EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup );//获取事件标准组的值(不会改变它的值)

    在中断中需要使用xEventGroupGetBitsFromISR这个函数。

    3)编程试验

    下面我们以一个例子来演示事件标志组的使用。

    和前几期的例子一样,我们还是使用cubemx建立三个任务,优先级各不相同。

    生成keil工程:

    编写代码如下,首先是事件标志组的创建:

    我们先编写在最低优先级的任务DefaultTask中发送事件,第1s发送事件位bit0,第2s发生事件位bit1,如此循环:

    在中等优先级任务Task02中,等待事件位bit0和bit1,都等到后,清零,并发送事件位bit3:

    在高优先级任务Task03中,等待事件位bit3,等到后不清零:

    这个程序运行结果如下图:

    初始时,优先级较高的两个任务都在等待事件,只有最低优先级任务DefaultTask可以运行;

    第1s时DefaultTask发送了事件bit0,第2s时DefaultTask发送了事件bit1;

    由于Task02设置的是同时等待bit0和bit1,所以,到DefaultTask发完bit1时,Task02才等到了它需要的所有事件位,等到之后事件位清0;

    然后,Task02发送了事件位bit3;

    Task03等待到bit3后,由于设置的是不清零,该bit3事件位它是一直有效的;所以Task03之后循环运行到等待事件位bit3时不会再被阻塞,而是立即返回执行。会不停地打印输出Task03 has waited event bit3。

    好了,本节的内容就到这里了。

    如果觉得有用可以关注作者微信号“小白白学电子”,在公众号可以找到代码和资料下载地址:

  • 相关阅读:
    【java苍穹外卖项目实战三】nginx反向代理和负载均衡
    【DLoopDetector(C++)】DBow2词袋模型&&loop close学习
    21天学习挑战赛(2)图解设备树的使用
    工业智能网关BL110应用之五十一: 数据上传云金鸽MQTT的配置
    Spring学习|Bean的作用域、自动装配Bean、注解实现自动装配、Spring注解开发
    modbus报文
    Nmap爆破MySQL弱口令漏洞:解决报错Accounts: No valid accounts found
    Karmada更高效地实现故障转移
    计算机毕业设计之java+javaweb的学生信息管理系统
    企业工程项目管理系统源码(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管理)
  • 原文地址:https://blog.csdn.net/little_grapes/article/details/125882383