FreeRTOS的事件标志组

之前介绍了使用信号量来完成同步,但是使用信号量来同步的话,任务只能与单个的事件或任务进行同步。有时候某个任务可能会需要与多个事件或任务进行同步,此时信号量就无能为力了。freertos 提供了一个可选的解决方法,那就是事件标志组。
事件标志位可以理解为一个bit位,多个事件位就组成了事件标志组,freertos可选8个事件标志位或者24个事件标志位,具体是由configuse_16_bit_ticks来确定,它为1的时候是8个标准位,为0时是24个标志位!
创建标志组
eventgrouphandle_t xeventgroupcreate( void );返回值:
创建失败返回null,创建成功返回句柄
置位api函数
eventbits_t xeventgroupsetbits( eventgrouphandle_t xeventgroup, const eventbits_t uxbitstoset );参数:
xeventgroup:需要操作的事件标志组的句柄
uxbitstoset:写入数值,例如0x09就表示置位第0位和第三位
读取事件组的位
eventbits_t xeventgroupwaitbits( const eventgrouphandle_t xeventgroup, const eventbits_t uxbitstowaitfor, const basetype_t xclearonexit, const basetype_t xwaitforallbits, ticktype_t xtickstowait );参数:
xeventgroup:事件标志组的句柄
uxbitstowaitfor:需要等待的标志位
xclearonexit:是否需要清除标志位
xwaitforallbits:是否等待所有设定标志位
xtickstowait:最大等待时间
注意:更多api函数,请参考官方相关
附上简单使用应用
#include stm32f10x.h#include #include freertos.h#include task.h#include event_groups.h#define start_task_prio 1 //任务优先级#define start_stk_size 128 //任务堆栈大小taskhandle_t starttask_handler; //任务句柄void start_task(void *pvparameters);//任务函数#define led0_task_prio 2 //任务优先级#define led0_stk_size 50 //任务堆栈大小taskhandle_t led0task_handler; //任务句柄void led0_task(void *p_arg); //任务函数eventgrouphandle_t event_handle = null;//事件标志组的句柄void led_init(void){ gpio_inittypedef gpio_initstructure; //定义结构体变量 rcc_apb2periphclockcmd(rcc_apb2periph_gpioc,enable); //开启时钟 gpio_initstructure.gpio_pin=gpio_pin_0; //选择你要设置的io口 gpio_initstructure.gpio_mode=gpio_mode_out_pp; //设置推挽输出模式 gpio_initstructure.gpio_speed=gpio_speed_50mhz; //设置传输速率 gpio_init(gpioc,&gpio_initstructure); //初始化gpio gpio_setbits(gpioc,gpio_pin_0); //将led端口拉高,熄灭led}int main( void ) { nvic_prioritygroupconfig(nvic_prioritygroup_4);//设置系统中断优先级分组 4 led_init(); //初始化 led //创建任务标志组 event_handle = xeventgroupcreate(); //置位标志位 xeventgroupsetbits( ( eventgrouphandle_t) event_handle, ( eventbits_t ) 0x08 ); //创建开始任务 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(); //进入临界区 //创建 led0 任务 xtaskcreate( (taskfunction_t )led0_task, (const char* )led0_task, (uint16_t )led0_stk_size, (void* )null, (ubasetype_t )led0_task_prio, (taskhandle_t* )&led0task_handler ); vtaskdelete(starttask_handler); //删除开始任务 taskexit_critical(); //退出临界区}//led0 任务函数void led0_task(void *pvparameters){ while(1) { xeventgroupwaitbits( ( eventgrouphandle_t ) event_handle, //句柄 ( eventbits_t ) 0x08, //需要等待的位 ( basetype_t ) pdtrue , //需要清零 ( basetype_t ) pdtrue, //等待所有设定标志位 ( ticktype_t ) portmax_delay );//死等待 if(gpio_readinputdatabit( gpioc, gpio_pin_0)) { gpio_resetbits( gpioc, gpio_pin_0); } else { gpio_setbits( gpioc, gpio_pin_0); } //置位标志位 xeventgroupsetbits( ( eventgrouphandle_t) event_handle, ( eventbits_t ) 0x08 ); vtaskdelay(400); }}注意:如果led0任务中的置位函数,那么led0函数只会运行一次,因为标志位已经清除了,需要再次置位标志位才会继续运行!
--end--

LG预计于2024年向三星供应90至110万块W-OLED电视面板
基于抄板精度问题
灯具的种类百科:你分得清哪些是可以调光的吗
TRUEC2技术的高性能LED射灯方案
下拉电阻的作用原理
FreeRTOS的事件标志组
关于EMC问题的测试
使用IP平台开发FPGA并进行应用设计
Cortex-A8处理器:AM335x的特点及应用介绍
三星无线充电器创造及发展变迁史详解
Pixel3系列频繁曝内存管理问题 谷歌官方回应称要等到12月推送修复
赛灵思、ADI、瑞萨电子等ADAS解决方案TOP8
摩托罗拉推出最便宜的扬声器模块
什么是电机标定?电机标定的工作原理
基于电脑软件的任意波形发生器SIG852初识(类似虚拟示波器)
双离合的种类以及优缺点
关于提升射频功率放大器的效率方法介绍
异步电机中的转子条数的定义、影响
变压器差动保护中电流互感器TA及其联接组的若干问题探讨
看到这个,你还把钱放到余额宝吗?你们有人放余额宝没?放多少呢