我们在学习FreeRTOS的时候,可以用信号量来进行任务同步,但是使用信号量同步时任务只能与单个的事件或者任务进行同步。
但当我们有时候需要与多个事件或者多个任务进行同步时,此时信号量就无能为力。
所以为了应对上述情况,我们可以使用事件标志组来解决。
事件位用来表明某个事件是否发生过,我们可以用一条消息,例如当按键按下去的时候,我们可以将某个位置1。
我们现在了解一下事件组。
一个事件组就是一组的事件位,事件组中的事件位通过位号来进行访问。
事件标志组的句柄结构为 EventGroupHandle_t 。当宏 configUSE_16_BIT_TIKCS 为1的时候,事件标志组可以存储8个事件位,当configUSE_16_BIT_TIKCS 为0的时候可以存储24个事件位。
所有的事件位都存储在一个无符号的 EventBits_t 类型的变量中。
1.创建事件标志组:xEventGroupCreate
参数:无
返回值:NULL创建失败
2.设置事件位:xEventGroupSetBits
参数:1.要操作的事件标志组的句柄
2.要设置的时间位 例如 1 设置0000 0000 的最低位 就设置0X01,要设置bit3置1,就设置0X08,当然可以两个位一起设置,要置bit3和bit1为1,就设置0X09
返回值:在将指定事件位置1后的事件组值
3.等待的事件为:EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
const TickType_t xTicksToWait );
参数:
xEventGroup :事件标志组的句柄
uxBitsToWaitFor:等带时间标志组的事件位
xClearOnExit:如果为pdTRUE退出EventGroupWaitBits之后,事件标志组的位都清零。如果为pdFLASE,那就保留
xWaitForAllBits:如果为pdTRUE设置的位都必须为1或者阻塞时间到才会退出。如果为pdFLASE,只要有一个位为1,xEventGroupWaitBits就退出
xTicksToWait :阻塞时间
接下来我们来写一下程序,来学一下事件标志组的基本流程。
#define EVENTBIT_0 (1<<0) //事件位
#define EVENTBIT_1 (1<<1)
#define EVENTBIT_2 (1<<2)
#define EVENTBIT_ALL (EVENTBIT_1|EVENTBIT_2)
/* 事件任务句柄 */
static EventGroupHandle_t EventGroupHandle;
//设置一下事件位,你要让哪一位为1
EventGroupHandle =xEventGroupCreate(); //创建事件
/**********************************************************************
* @ 函数名 : eventsetbit_task
* @ 功能说明: eventsetbit_task任务主体
* @ 参数 :
* @ 返回值 : 无
********************************************************************/
static void eventsetbit_task(void* parameter)
{
while (1)
{
if(EventGroupHandle != NULL) //判断事件标志组是否创建成功
{
if( Key_Scan(GPIOC,GPIO_Pin_13) == KEY_ON ) //一个按键按下,第二位位为1
{
xEventGroupSetBits(EventGroupHandle,EVENTBIT_2);
printf("EVENTBIT_2\r\n");
}
if(Key_Scan(GPIOA,GPIO_Pin_0 == KEY_ON)) //第二个按键按下,第一位位为1
{
xEventGroupSetBits(EventGroupHandle,EVENTBIT_1); //设置事件位函数
printf("EVENTBIT_1\r\n");
}
}
vTaskDelay(10);
}
}
/*****************************************************************/
static void eventgroup_task(void* parameter)
{
while (1)
{
if(EventGroupHandle != NULL)
{
EVENTVALUE= xEventGroupWaitBits((EventGroupHandle_t) EventGroupHandle, //等待事件,当位1和位2都为1时,才会进入到这函数里面
(EventBits_t ) EVENTBIT_ALL,
(BaseType_t ) pdTRUE,
(BaseType_t ) pdTRUE,
(TickType_t ) portMAX_DELAY );
printf("事件标志组的值为%d\r\n",EVENTVALUE);
}
vTaskDelay(15);
}
}