[FreeRTOS 功能应用] 事件组 功能应用

server/2024/9/23 4:09:52/

文章目录

    • 一、基础知识点
    • 二、代码讲解
    • 三、结果演示
    • 四、代码下载


一、基础知识点

[FreeRTOS 基础知识] 事件组 概念
[FreeRTOS 内部实现] 事件组

本实验是基于STM32F103开发移植FreeRTOS实时操作系统,事件组实战操作。(当task1和task2同时完成,才执行task3)
使用工具:Keil、串口工具


二、代码讲解

1、使用xEventGroupCreate函数创建事件组

// 路径:项目\Core\Src\freertos.c
// 全局变量
EventGroupHandle_t g_EventGroup;
g_EventGroup = xEventGroupCreate ( );

2、使用osThreadCreate创建三个任务

// 创建两个任务
osThreadDef(Task1, vTask_a, osPriorityHigh, 0, 1000);
Task1_Handle = osThreadCreate(osThread(Task1), NULL);
if( Task1_Handle != NULL )
{printf("Succeeded in creating Sender1_Handle Queue. Procedure!\n\r");
}
else
{printf("Fail in creating Sender1_Handle Queue. Procedure!\n\r");
}osThreadDef(Task2, vTask_b, osPriorityNormal, 0, 1000);
Task2_Handle = osThreadCreate(osThread(Task2), NULL);		
if( Task2_Handle != NULL )
{printf("Succeeded in creating Seceiver_Handle Queue. Procedure!\n\r");
}
else
{printf("Fail in creating Seceiver_Handle Queue. Procedure!\n\r");
}		osThreadDef(Task3, vTask_c, osPriorityNormal, 0, 1000);
Task3_Handle = osThreadCreate(osThread(Task3), NULL);		
if( Task3_Handle != NULL )
{printf("Succeeded in creating Seceiver_Handle Queue. Procedure!\n\r");
}
else
{printf("Fail in creating Seceiver_Handle Queue. Procedure!\n\r");
}		

函数中通过osThreadDef 宏构建osThreadDef_t 结构体,名称os_thread_def_##name(## 表示字符拼接),结构体成员包括 :#name 任务名称;thread 任务处理函数;priority 任务优先级;instances 实例; stacksz 栈大小;

#define osThreadDef(name, thread, priority, instances, stacksz)  \
const osThreadDef_t os_thread_def_##name = \
{ #name, (thread), (priority), (instances), (stacksz), NULL, NULL }

将构建的osThreadDef_t 结构体传入osThreadCreate函数中,实际调用xTaskCreate函数创建任务。

osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument)
{TaskHandle_t handle;if (xTaskCreate((TaskFunction_t)thread_def->pthread,(const portCHAR *)thread_def->name,thread_def->stacksize, argument, makeFreeRtosPriority(thread_def->tpriority),&handle) != pdPASS)  {return NULL;} return handle;
}

任务实现:task1完成后执行task2;当task1和task2都完成后执行task3

3、task1任务函数vTask_a实现

void vTask_a(void const * argument)
{for(;;){xEventGroupSetBits(g_EventGroup, EVENT_A);printf("DWB -- vTask_a \n\r");xEventGroupWaitBits(g_EventGroup, EVENT_C, TRUE, TRUE, pdMS_TO_TICKS(10));vTaskDelay(pdMS_TO_TICKS(250));   // 延时250ms}	
}

通过xEventGroupSetBits函数,设置 g_EventGroup 结构体中的事件状态标志位,表示task1执行完成。
通过xEventGroupWaitBits函数,等待task3完成后清除标志位并执行。(EVENT_C)

4、task2任务函数vTask_b实现

void vTask_b(void const * argument)
{for(;;){xEventGroupWaitBits(g_EventGroup, EVENT_A, FAILED, TRUE, pdMS_TO_TICKS(10));xEventGroupSetBits(g_EventGroup, EVENT_B);printf("DWB -- vTask_b \n\r");vTaskDelay(pdMS_TO_TICKS(300));   // 延时300ms}	
}

通过xEventGroupWaitBits函数,等待task1完成后不清除标志位并执行。(EVENT_A)
通过xEventGroupSetBits函数,设置 g_EventGroup 结构体中的事件状态标志位,表示task2执行完成。

5、task3任务函数vTask_c实现

void vTask_c(void const * argument)
{for(;;){xEventGroupWaitBits(g_EventGroup, EVENT_A|EVENT_B, TRUE, TRUE, pdMS_TO_TICKS(10));xEventGroupSetBits(g_EventGroup, EVENT_C);printf("DWB -- vTask_c \n\r");vTaskDelay(pdMS_TO_TICKS(300));   // 延时300ms}	
}

通过xEventGroupWaitBits函数,等待task1 和 task2完成后不清除标志位并执行。(EVENT_A|EVENT_B)
通过xEventGroupSetBits函数,设置 g_EventGroup 结构体中的事件状态标志位,表示task3执行完成。


三、结果演示

从串口可以看出,任务c是在任务a和任务b都完成之后执行。
在这里插入图片描述


四、代码下载

[ FreeRTOS ] 事件组 功能应用


http://www.ppmy.cn/server/55788.html

相关文章

【数据分享】全国乡村旅游重点镇(乡)数据(Excel/Shp格式/免费获取)

之前我们分享过从我国文化和旅游部官网整理的2018-2023年我国50个重点旅游城市星级饭店季度经营状况数据(可查看之前发布的文章)!文化和旅游部官网上也分享有很多与旅游相关的常用数据,我们基于官网发布的名单文件整理得到全国乡村…

基于SpringBoot+Vue的招生管理系统(带1w+文档)

基于SpringBootVue的招生管理系统(带1w文档) 通过招生管理系统的研究可以更好地理解系统开发的意义,而且也有利于发展更多的智能系统,解决了人才的供给和需求的平衡问题,招生管理系统的开发建设,由于其开发周期短&…

Kafka 进阶指南

Kafka 进阶指南 引言 在掌握了 Kafka 的基本概念和操作后,我们可以进一步探索 Kafka 的高级特性和使用技巧,以提高其性能、可扩展性和可靠性。本指南将介绍 Kafka 的进阶主题,包括性能调优、扩展策略、数据复制、日志压缩、流处理和安全性。…

价格预言机的使用总结(一):Chainlink篇

文章首发于公众号:Keegan小钢 前言 价格预言机已经成为了 DeFi 中不可获取的基础设施,很多 DeFi 应用都需要从价格预言机来获取稳定可信的价格数据,包括借贷协议 Compound、AAVE、Liquity ,也包括衍生品交易所 dYdX、PERP 等等。…

从零开始读RocketMq源码(一)生产者启动

目录 前言 获取源码 总概论 生产者实例 源码 A-01:设置生产者组名称 A-02:生产者服务启动 B-01:初始化状态 B-02:该方法再次对生产者组名称进行校验 B-03:判断是否为默认生产者组名称 B-04: 该方法是为了实例化MQClientInstance对…

elementPlus自定义el-select下拉样式

如何在f12元素选择器上找到下拉div呢? 给el-select添加 :popper-append-to-body"false" 即可,这样就可以将下拉框添加到body元素中去,否则当我们失去焦点,下拉就消失了,在元素中找不到el-select。剩下就可以…

c++11新特性-8-初始化列表

文章目录 初始化列表1.统一初始化2. std::initializer_list 初始化列表 1.统一初始化 //初始化整型 int a{12};//初始化数组 int a[] {1,2,3,4}; int a[] {1,2,3,4};//初始化指针 int* p new int{10}; double* p new double(1.23); int* arry new int[3]{1,2,3};2. std::i…

记录第一次使用air热更新golang项目

下载 go install github.com/cosmtrek/airlatest 下载时提示: module declares its path as: github.com/air-verse/air but was required as: github.com/cosmtrek/air 此时,需要在go.mod中加上这么一句: replace github.com/cosmtrek/air &…