基于STM32F407的FreeRTOS学习笔记(10)

发布时间:2024-04-12  

在介绍二进制信号量时曾经讲过,二进制信号量可以代替我们裸机开发中的标志位来使用。在裸机开发中我们使用标志位来表示某个事件是否发生,并且其他程序利用标记位的状态来判断程序是否可以继续进行。但是这种大量使用标记位的情况会导致代码的逻辑异常的复杂。

图片

虽然使用二进制信号量可以很好的实现标志位的实现以及相应的任务安排,但是二进制信号量并不适用于大量的标志位。因为一个二进制信号量只能表示一个事件,假如我们的程序有大量的事件那有没有办法不用二进制信号量可以很好的管理这些事件呢?

这就是本期介绍的内容:事件位和事件组

图片

在FreeRTOS中我们把一个用作判断事件是否发生的情况作为事件位,用0或1表示。它可以用来表示一个事件是否发生。比如函数Test是否被调用,用户是否按下按键等等事件。

图片

这些由多个事件位构成的集合则被称为事件组。事件组中不同的位编号代表不同的事件位。例如位编号0(0x00)用来代表函数Test是否被调用,事件组位编号1(0x01)代表用户是否按下按钮……

图片

FreeRTOS 通过相对应的宏定义来确定事件组的长度(包含多少事件位)例如config_16_BIT_TICKS为0的话则代表一个事件组可以包含24位事件位。

使用事件组

和之前的其他内容一样,使用事件组的准备也要包含相关头文件、定义相对应的宏定义、调用创建函数。

图片

事件组的创建函数非常简单,只需要定义一个事件组的句柄来接收事件组创建函数的返回值即可。事件组的长度前面说过利用宏定义来确定时间组长度。

图片

等待事件组的函数和信号量相似,设置我们需要等待事件发生的位并且设置超时时间。但是注意的是我们选择需要等待的位不能设置为0

第三个参数用来设置等到事件位触发后是否清空数据位。

其中的第四个参数xWaitForAllBits则是用来 确定位之间的与或关系 ,例如如果我的位设置是0x03即第0和第1位,如果xWaitForAllBits是pdTRUE则需要第0和第1位同时为1,如果是pdFalse则第0和第1只要有一个事件触发就执行。

图片

该函数用来设置事件位,需要注意的是该函数的返回值是事件组各位的值,但是如果有更高优先级的任务在等待则会立刻清空事件位,所以会导致事件位返回时被清空。


测试实验


首先我们创建一个事件组,宏定义中定义这个事件组总共有24个事件位。


EventHandler = xEventGroupCreate();

接着我们创建一个按键检测任务,当按钮一按下时,将事件组第0位置1,当按钮二按下时,将事件组第1位置1;


void Low_Task(void * pvParameters)//参数为 void * pvParameters

{

  while(1)

  {

    if(KEY_Scan(0)==1)

    {

        xEventGroupSetBits(EventHandler,1< < 0);//1< < 0是0x01

    }

    if(KEY_Scan(0)==2)

    {

      xEventGroupSetBits(EventHandler,1< < 1);//1< < 1是0x02

    }    

    vTaskDelay(10);

  }

}

最后我们设置一个轮询事件组的语句,并且设置第四个参数为pdFlase,当有一个按键按下时,LED翻转。


void Mid_Task(void * pvParameters)//参数为 void * pvParameters

{

  BaseType_t err;

  while(1)

  {

    err = xEventGroupWaitBits(

                       (const EventGroupHandle_t) EventHandler,

                       (const EventBits_t) 0x03,

                       (const BaseType_t) pdTRUE,

                       (const BaseType_t) pdFALSE,

                       (TickType_t) portMAX_DELAY  );

      HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);


    vTaskDelay(10);

  }

}

接着我们把pdFlase改成pdTRUE,当两个按钮(事件)都触发过的时候,才能执行任务。


void Mid_Task(void * pvParameters)//参数为 void * pvParameters

{

  BaseType_t err;

  while(1)

  {

    err = xEventGroupWaitBits(

                       (const EventGroupHandle_t) EventHandler,

                       (const EventBits_t) 0x03,

                       (const BaseType_t) pdTRUE,

                       (const BaseType_t) pdTRUE,

                       (TickType_t) portMAX_DELAY  );

      HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);


    vTaskDelay(10);

  }

}

其中xEventGroupWaitBits返回值会根据不同的情况而改变。

图片

如果因为事件组全部触发而完成的函数的话,err返回函数清空前的事件组的值。

图片

如果因为超时而导致阻塞结束的话,err返回的则是当前事件组的值。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>