总目录
FreeRTOS学习—“任务”篇
FreeRTOS学习—“消息队列”篇
FreeRTOS学习—“信号量”篇
FreeRTOS学习—“事件组”篇
FreeRTOS学习—“定时器”篇
FreeRTOS还有一个进程同步的组件,就是event_group事件组。
事件是一种实现任务间通信的机制,主要用于实现多任务间的同步,但事件通信只能是事件类型的通信,无数据传输。
与信号量不同的是,它可以实现一对多,多对多的同步。即一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。同样,也可以是多个任务同步多个事件。
就像是一个全局变量,每一位表示一个事件,通过事件位的设置和读取,来同步最多24类消息,允许一个或者多个任务来设置和读取,例如一些按键操作,按下不同的按键,来启动或者控制不同的任务进行。
通过配置宏定义,来决定了同步数据类型的多少
#define configUSE_16_BIT_TICKS 0
#if configUSE_16_BIT_TICKS == 1
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x0100U
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x0200U
#define eventWAIT_FOR_ALL_BITS 0x0400U
#define eventEVENT_BITS_CONTROL_BYTES 0xff00U
#else
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL
#define eventWAIT_FOR_ALL_BITS 0x04000000UL
#define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL
#endif
当configUSE_16_BIT_TICKS==0的时候,整个数据是4个字节,消息占据了三个字节,一共是24种
当configUSE_16_BIT_TICKS==1的时候,整个数据是2个字节,消息占据了一个字节,一共是8种。
这块是猜测的,不知道对不对
demo程序
下面程序启用了两个任务,其中setevent用来置位,每隔1秒置不同的数据位,即传输不同的消息;另一个任务readevent,读取这些事件,并处理显示收到的什么事件。
#define send_1 (0x01 << 0)
#define send_2 (0x01 << 1)
#define send_3 (0x01 << 2)
#define send_4 (0x01 << 3)
static EventGroupHandle_t g_event_group;
static void setevent_task(void *pvParameter)
{
while (1)
{
xEventGroupSetBits(g_event_group, send_1);
vTaskDelay(1000 / portTICK_PERIOD_MS);
xEventGroupSetBits(g_event_group, send_2);
vTaskDelay(1000 / portTICK_PERIOD_MS);
xEventGroupSetBits(g_event_group, send_3);
vTaskDelay(1000 / portTICK_PERIOD_MS);
xEventGroupSetBits(g_event_group, send_4);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void readevent_task()
{
EventBits_t uxBits;
while (1)
{
uxBits = xEventGroupWaitBits(g_event_group, send_1 | send_2 | send_3 | send_4, true, false, portMAX_DELAY);
if (uxBits & send_1)
{
printf("get 1 \n");
}
if (uxBits & send_2)
{
printf("get 2\n");
}
if (uxBits & send_3)
{
printf("get 3 \n");
}
if (uxBits & send_4)
{
printf("get 4 \n");
}
vTaskDelay(300 / portTICK_PERIOD_MS);
}
}
void app_main()
{
g_event_group = xEventGroupCreate();
xTaskCreate(&readevent_task, "readevent_task", 2048, NULL, 5, NULL);
xTaskCreate(&setevent_task, "setevent_task", 2048, NULL, 5, NULL);
}
重点函数
创建事件组
EventGroupHandle_t xEventGroupCreate( void )
参数 | 含义 |
---|---|
返回值 | NULL 表示没有足够的堆空间分配给事件组而导致创建失败。 |
非 NULL 值表示事件组创建成功。此返回值应当保存下来,以作为操作此事件组的句柄。 |
设置事件组
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
参数 | 含义 |
---|---|
xEventGroup | 目标事件组的句柄。这个句柄即是调用 xEventGroupCreate()创建该队列时的返回值。 |
uxBitsToSet | 要设置的事件标志位 |
返回值 | 返回在调用这个函数之后的事件组的值 |
清除事件组
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )
参数 | 含义 |
---|---|
xEventGroup | 目标事件组的句柄。这个句柄即是调用 xEventGroupCreate()创建该队列时的返回值。 |
uxBitsToSet | 要清除的事件标志位 |
返回值 | 返回在调用这个函数之后的事件组的值 |
读取事件组
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait )
参数 | 含义 |
---|---|
xEventGroup | 目标事件组的句柄。这个句柄即是调用 xEventGroupCreate()创建该队列时的返回值。 |
uxBitStowait | 用于指示要在事件组内测试的位的逐位值。例如,要等待位0和位2,请将uxBitsToWaitFor设置为0x05 |
xClearOnExit | true表示读取之后将所在位清空,false表示不清空。 |
xWaitForAllBits | true表示所有事件位都为真的时候才返回;false表示有任意一位被设置就能返回。 |
xTicksToWait | 阻塞超时时间。如果在发送时队列已满,这个时间即是任务处于阻塞态等待队列空间有效的最长等待时间。如 果 xTicksToWait 设 为 0 ,并且队列已满,则xQueueSendToFront()与 xQueueSendToBack()均会立即返回。阻塞时间是以系统心跳周期为单位的,所以绝对时间取决于系统心跳频率。常量 portTICK_RATE_MS 可以用来把心跳时间单位转换为毫秒时间单位。如果把 xTicksToWait 设置为 portMAX_DELAY ,并且在FreeRTOSConig.h 中设定 INCLUDE_vTaskSuspend 为 1,那么阻塞等待将没有超时限制。 |
删除事件组
void vEventGroupDelete( EventGroupHandle_t xEventGroup )
参数 | 含义 |
---|---|
xEventGroup | 目标事件组的句柄。这个句柄即是调用 xEventGroupCreate()创建该队列时的返回值。 |
结束
这部分内容看起来就很清楚明了,适合多多使用啊。
FreeRTOS学习—“任务”篇
FreeRTOS学习—“消息队列”篇
FreeRTOS学习—“信号量”篇
FreeRTOS学习—“事件组”篇
FreeRTOS学习—“定时器”篇