任务通知—模拟事件标志组
描述:使用任务通知模拟事件标志组也时通过操作一个32位任务通知值的位来实现的,只不过是间接操作的,比事件标志组操作要繁琐一点,个人建议使用事件标志组替代任务通知模拟。
#include "event_groups.h" //头文件
EventGroupHandle_t EventGroupHandler;//事件标志组句柄声明
#define EVENTBIT_0 (1<<0)//事件标志位 0
#define EVENTBIT_1 (1<<1)//事件标志位 1
#define EVENTBIT_2 (1<<2)//事件标志位 2
#define EVENTBIT_ALL (EVENTBIT_0|EVENTBIT_1|EVENTBIT_2)
EventGroupHandler=xEventGroupCreate();//创建一个事件标志组
以上为事件标志组的声明与创建过程。
#include "FreeRTOS.h"
#include "task.h"
#include "limits.h"
#define EVENTBIT_0 (1<<0) //事件位0
#define EVENTBIT_1 (1<<1)
#define EVENTBIT_2 (1<<2)
以上为任务通知模拟事件标志组的声明
//设置事件位的任务
void eventsetbit_task(void *pvParameters)
{
u8 key;
while(1)
{
if(EventGroupTask_Handler!=NULL)
{
key=KEY_Scan(0);
switch(key)
{
case KEY1_PRES:
xTaskNotify((TaskHandle_t )EventGroupTask_Handler,//接收任务通知的任务句柄
(uint32_t )EVENTBIT_1, //要更新的bit
(eNotifyAction )eSetBits); //更新指定的bit
break;
case KEY2_PRES:
xTaskNotify((TaskHandle_t )EventGroupTask_Handler,//接收任务通知的任务句柄
(uint32_t )EVENTBIT_2, //要更新的bit
(eNotifyAction )eSetBits); //更新指定的bit
break;
case KEY3_PRES:
xTaskNotify((TaskHandle_t )EventGroupTask_Handler,//接收任务通知的任务句柄
(uint32_t )EVENTBIT_3, //要更新的bit
(eNotifyAction )eSetBits); //更新指定的bit
break;
}
}
vTaskDelay(10); //延时10ms,也就是10个时钟节拍
}
}
中断服务函数的事件设置如下:
//外部中断4服务程序
#define EVENTBIT_0 (1<<0)
void EXTI4_IRQHandler(void)
{
BaseType_t xHigherPriorityTaskWoken;
xTaskNotifyFromISR((TaskHandle_t )EventGroupTask_Handler, //任务句柄
(uint32_t )EVENTBIT_0, //要更新的bit
(eNotifyAction )eSetBits, //更新指定的bit
(BaseType_t* )xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
EXTI_ClearITPendingBit(EXTI_Line4);//清除LINE4上的中断标志位
}
获取任务通知
//事件标志组处理任务
void eventgroup_task(void *pvParameters)
{
u8 enevtvalue;
static u8 event0flag,event1flag,event2flag;
uint32_t NotifyValue;
BaseType_t err;
while(1)
{
//获取任务通知值
err=xTaskNotifyWait((uint32_t )0x00, //进入函数的时候不清除任务bit
(uint32_t )ULONG_MAX, //退出函数的时候清除所有的bit
(uint32_t* )&NotifyValue, //保存任务通知值
(TickType_t )portMAX_DELAY); //阻塞时间
if(err==pdPASS) //任务通知获取成功
{
if((NotifyValue&EVENTBIT_0)!=0) //事件0发生
{
event0flag=1;
}
else if((NotifyValue&EVENTBIT_1)!=0) //事件1发生
{
event1flag=1;
}
else if((NotifyValue&EVENTBIT_2)!=0) //事件2发生
{
event2flag=1;
}
enevtvalue=event0flag|(event1flag<<1)|(event2flag<<2); //模拟事件标志组值
if((event0flag==1)&&(event1flag==1)&&(event2flag==1)) //三个事件都同时发生
{
event0flag=0; //标志清零
event1flag=0;
event2flag=0;
}
}
else
{
printf("任务通知获取失败\r\n");
}
}
}
总结:任务通知模拟事件标志组的核心就是任务通知值的设置与读取过程,获取通知的时候需要读取该32位的值与相应事件位比较判定事件是否发生,发生则FLAG0置1,它无法判定多个事件是否发生,只能用FLAG判定。
多个FLAG置1则表示模拟事件标志组达成。
真事件标志组可以设置多个事件位同时置1才释放阻塞,也可以单个事件置1