1、 介绍事件组
①事件组的前8bit代表状态,剩下的代表事件。
#define eventCLEAR_EVENTS_ON_EXIT_BIT 0x01000000UL/* 退出时,将事件清除*/
#define eventUNBLOCKED_DUE_TO_BIT_SET 0x02000000UL/* 这个位为1代表没有超时,否则代表任务超时*/
#define eventWAIT_FOR_ALL_BITS 0x04000000UL/* 所有事件生效才接触任务*/
#define eventEVENT_BITS_CONTROL_BYTES 0xff000000UL/* 控制位和非控制位的掩码*/
②事件组的结构体(_比较简单)
typedef struct xEventGroupDefinition
{
EventBits_t uxEventBits; /*< 发生事件组 */
List_t xTasksWaitingForBits; /*< 等待设置的任务列表。 */
uint8_t ucStaticallyAllocated; /*< 如果为pdTRUE代表不能释放。 */
} EventGroup_t;
③使用事件组要包含#include "event_groups.h"头文件
④FreeRTOS是不允许不确定的操作在中断和临界段中发生的,所以xEventGroupSetBitsFromISR()函数(是个宏定义)给FreeRTOSde 守护任务发送一个消息,让置位事件组的操作在守护任务中完成,守护任务是基于调度锁而非临界段的机制来实现
守护任务就是软件定时器任务
#define xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken ) \
xTimerPendFunctionCallFromISR( vEventGroupSetBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToSet, pxHigherPriorityTaskWoken )
2、 创建任务和事件组
void m_create_event_group(void)
{
BaseType_t xReturn = pdPASS;
Event_Handle = xEventGroupCreate();
if(NULL != Event_Handle)
LOG_BLE("Event_Handle c\n");
xReturn = xTaskCreate((TaskFunction_t )Led_Task,
(const char* )"Led_Task",
(uint16_t )512,
(void* )NULL,
(UBaseType_t )2,
(TaskHandle_t* )&Led_Task_Handle);
if(pdPASS == xReturn)
{
LOG_BLE("Led_Task create ok\r\n");
}
xReturn = xTaskCreate((TaskFunction_t )Key_Task,
(const char* )"Key_Task",
(uint16_t )512,
(void* )NULL,
(UBaseType_t )2,
(TaskHandle_t* )&Key_Task_Handle);
if(pdPASS == xReturn)
{
LOG_BLE("Key_Task create ok\r\n");
}
}
3、 编写内存的测试任务入口函数
#include "event_groups.h"
#ifndef TAG_BLE
#define LOG_BLE(...)
#endif
#define KEY1_EVENT (0x01 << 0)
#define KEY2_EVENT (0x01 << 1)
#define KEY3_EVENT (0x01 << 2)
#define KEY4_EVENT (0x01 << 3)
static EventGroupHandle_t Event_Handle =NULL;
static TaskHandle_t Led_Task_Handle = NULL;
static TaskHandle_t Key_Task_Handle = NULL;
static void Led_Task(void* parameter)
{
uint32_t r_event;
while (1)
{
r_event = xEventGroupWaitBits(Event_Handle,
KEY1_EVENT|KEY2_EVENT|KEY3_EVENT|KEY4_EVENT,
pdTRUE, /* 退出时清除事件位*/
pdFALSE, /* 满足感兴趣的所有事件*/
portMAX_DELAY);
LOG_BLE("r_event:0x%X\n",r_event);
if (r_event&KEY1_EVENT)
{
LOG_BLE("key1 push\n");
}
if (r_event&KEY2_EVENT)
{
LOG_BLE("key2 push\n");
}
if (r_event&KEY3_EVENT)
{
LOG_BLE("key3 push\n");
}
if (r_event&KEY4_EVENT)
{
LOG_BLE("key4 push\n");
}
}
}
static void Key_Task(void* parameter)
{
uint8_t button1_sta = 0;
uint8_t button2_sta = 0;
uint8_t button3_sta = 0;
uint8_t button4_sta = 0;
while (1)
{
if( READ_BUTTON1_P11() == BUTTON_PUSH )
{
if (0 == button1_sta)
{
LOG_BLE ( "set KEY1_EVENT\n" );
xEventGroupSetBits(Event_Handle,KEY1_EVENT);
button1_sta = 1;
}
OPEN_LED13();
} else
{
button1_sta = 0;
CLOSE_LED13();
}
if( READ_BUTTON2_P12() == BUTTON_PUSH )
{
if (0 == button2_sta)
{
LOG_BLE ( "set KEY2_EVENT\n" );
xEventGroupSetBits(Event_Handle,KEY2_EVENT);
button2_sta = 1;
}
OPEN_LED14();
} else
{
button2_sta = 0;
CLOSE_LED14();
}
if( READ_BUTTON3_P24() == BUTTON_PUSH )
{
if ( 0 == button3_sta)
{
LOG_BLE ( "set KEY3_EVENT\n" );
xEventGroupSetBits(Event_Handle,KEY3_EVENT);
button3_sta = 1;
}
OPEN_LED15();
} else
{
button3_sta = 0;
CLOSE_LED15();
}
if( READ_BUTTON4_P25() == BUTTON_PUSH )
{
if ( 0 == button4_sta)
{
LOG_BLE ( "set KEY4_EVENT\n" );
xEventGroupSetBits(Event_Handle,KEY4_EVENT);
button4_sta = 1;
}
OPEN_LED16();
} else
{
button4_sta = 0;
CLOSE_LED16();
}
vTaskDelay(20);
}
}
实验说明和现象
①Key_Task有按键发生,将发送对应的事件。
②Led_Task阻塞等待事件发生。当有任何一个事件位为发生将唤醒Led_Task打印相应的事件位。