FreeRTOS——事件标志组
事件标志组
事件标志组简介
使用信号量同步任务只能与单个时间或任务进行同步,如果要莫个任务与多个事件或者任务进行同步,这时需要事件标志组来处理。
事件标志组相关函数
事件标志组创建函数
设置事件位函数
获取事件标志组值函数
等待指定事件位函数
实验
要求
程序
主程序
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "lcd.h"
#include "key.h"
#include "beep.h"
#include "exti.h"
#include "string.h"
#include "malloc.h"
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 256
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//ÈÎÎñÓÅÏȼ¶
#define EVENTSETBIT_TASK_PRIO 2
//ÈÎÎñ¶ÑÕ»´óС
#define EVENTSETBIT_STK_SIZE 256
//ÈÎÎñ¾ä±ú
TaskHandle_t EventSetBit_Handler;
//ÈÎÎñº¯Êý
void eventsetbit_task(void *pvParameters);
//ÈÎÎñÓÅÏȼ¶
#define EVENTGROUP_TASK_PRIO 3
//ÈÎÎñ¶ÑÕ»´óС
#define EVENTGROUP_STK_SIZE 256
//ÈÎÎñ¾ä±ú
TaskHandle_t EventGroupTask_Handler;
//ÈÎÎñº¯Êý
void eventgroup_task(void *pvParameters);
//ÈÎÎñÓÅÏȼ¶
#define EVENTQUERY_TASK_PRIO 4
//ÈÎÎñ¶ÑÕ»´óС
#define EVENTQUERY_STK_SIZE 256
//ÈÎÎñ¾ä±ú
TaskHandle_t EventQueryTask_Handler;
//ÈÎÎñº¯Êý
void eventquery_task(void *pvParameters);
EventGroupHandle_t EventGroupHandler; //事件标志组任务句柄
#define EVENTBIT_0 (1<<0) //事件位
#define EVENTBIT_1 (1<<1)
#define EVENTBIT_2 (1<<2)
#define EVENTBIT_ALL (EVENTBIT_0|EVENTBIT_1|EVENTBIT_2)
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
delay_init(168);
uart_init(115200);
LED_Init();
KEY_Init();
EXTIX_Init();
my_mem_init(SRAMIN); //初始化内部内存池
//开始创建任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //给任务传递的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度器
}
//开始创建任务
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建事件标志组
EventGroupHandler=xEventGroupCreate(); //´´½¨Ê¼þ±êÖ¾×é
//创建设置事件标志位任务
xTaskCreate((TaskFunction_t )eventsetbit_task,
(const char* )"eventsetbit_task",
(uint16_t )EVENTSETBIT_STK_SIZE,
(void* )NULL,
(UBaseType_t )EVENTSETBIT_TASK_PRIO,
(TaskHandle_t* )&EventSetBit_Handler);
//创建事件标志组处理任务
xTaskCreate((TaskFunction_t )eventgroup_task,
(const char* )"eventgroup_task",
(uint16_t )EVENTGROUP_STK_SIZE,
(void* )NULL,
(UBaseType_t )EVENTGROUP_TASK_PRIO,
(TaskHandle_t* )&EventGroupTask_Handler);
//创建事件标志组查询任务
xTaskCreate((TaskFunction_t )eventquery_task,
(const char* )"eventquery_task",
(uint16_t )EVENTQUERY_STK_SIZE,
(void* )NULL,
(UBaseType_t )EVENTQUERY_TASK_PRIO,
(TaskHandle_t* )&EventQueryTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//设置事件标志位任务
void eventsetbit_task(void *pvParameters)
{
u8 key;
while(1)
{
if(EventGroupHandler!=NULL)
{
key=KEY_Scan(0);
switch(key)
{
case KEY1_PRES:
xEventGroupSetBits(EventGroupHandler,EVENTBIT_1);
break;
case KEY2_PRES:
xEventGroupSetBits(EventGroupHandler,EVENTBIT_2);
break;
}
}
vTaskDelay(10); //ÑÓʱ10ms£¬Ò²¾ÍÊÇ10¸öʱÖÓ½ÚÅÄ
}
}
//事件标志组处理任务
void eventgroup_task(void *pvParameters)
{
u8 num;
EventBits_t EventValue;
while(1)
{
if(EventGroupHandler!=NULL)
{
//等待事件标志组相应时间
EventValue=xEventGroupWaitBits((EventGroupHandle_t )EventGroupHandler,
(EventBits_t )EVENTBIT_ALL,
(BaseType_t )pdTRUE,
(BaseType_t )pdTRUE,
(TickType_t )portMAX_DELAY);
printf("事件标志组的值:%d\r\n",EventValue);
num++;
LED1=!LED1;
}
else
{
vTaskDelay(10); //ÑÓʱ10ms£¬Ò²¾ÍÊÇ10¸öʱÖÓ½ÚÅÄ
}
}
}
//时间查询任务
void eventquery_task(void *pvParameters)
{
u8 num=0;
EventBits_t NewValue,LastValue;
while(1)
{
if(EventGroupHandler!=NULL)
{
NewValue=xEventGroupGetBits(EventGroupHandler); //获取事件标志组
if(NewValue!=LastValue)
{
LastValue=NewValue;
printf("事件标志组的值:%d\r\n",NewValue);
}
}
num++;
if(num==10) //ÿ500msLED0ÉÁ˸һ´Î
{
num=0;
LED0=!LED0;
}
vTaskDelay(50); //ÑÓʱ50ms£¬Ò²¾ÍÊÇ50¸öʱÖÓ½ÚÅÄ
}
}
中断程序
#ifndef __EXTI_H
#define __EXIT_H
#include "sys.h"
void EXTIX_Init(void); //外部中断初始化
#endif
#include "exti.h"
#include "delay.h"
#include "key.h"
#include "FreeRTOS.h"
#include "event_groups.h"
#define EVENTBIT_0 (1<<0)
//ÍⲿÖжϳõʼ»¯³ÌÐò
//³õʼ»¯PE4ΪÖжÏÊäÈë.
void EXTIX_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
KEY_Init(); //°´¼ü¶ÔÓ¦µÄIO¿Ú³õʼ»¯
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//ʹÄÜSYSCFGʱÖÓ
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);//PE4 Á¬½Óµ½ÖжÏÏß4
/* ÅäÖÃEXTI_Line4 */
EXTI_InitStructure.EXTI_Line = EXTI_Line4;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //ÖжÏʼþ
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //ϽµÑØ´¥·¢
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //ÖжÏÏßʹÄÜ
EXTI_Init(&EXTI_InitStructure); //ÅäÖÃ
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; //ÍⲿÖжÏ4
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x06;//ÇÀÕ¼ÓÅÏȼ¶6
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //×ÓÓÅÏȼ¶0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //ʹÄÜÍⲿÖжÏͨµÀ
NVIC_Init(&NVIC_InitStructure); //ÅäÖÃ
}
//事件标志组的句柄
extern EventGroupHandle_t EventGroupHandler;
//外部中断服务函数
void EXTI4_IRQHandler(void)
{
BaseType_t Result,xHigherPriorityTaskWoken;
delay_xms(20); //消抖
if(KEY0==0)
{
Result=xEventGroupSetBitsFromISR(EventGroupHandler,EVENTBIT_0,&xHigherPriorityTaskWoken);
if(Result!=pdFAIL)
{
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
EXTI_ClearITPendingBit(EXTI_Line4);//清除中断标志位
}