[FreeRTOS 功能应用] 互斥访问与回环队列 功能应用

文章目录

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


一、基础知识点

[FreeRTOS 基础知识] 互斥访问与回环队列 概念
[FreeRTOS 内部实现] 互斥访问与回环队列
[FreeRTOS 内部实现] 创建任务 xTaskCreate函数解析

本实验是基于STM32F103开发移植FreeRTOS实时操作系统,实现多任务同时读写队列数据操作。
使用工具:Keil、串口工具


二、代码讲解

1、使用xQueueCreate函数 创建队列。

// 路径:项目\Core\Src\freertos.c
// 全局变量
QueueHandle_t g_xQueue;/* 创建队列,长度5,数据大小4个字节 */
g_xQueue = xQueueCreate(5, sizeof(int32_t));

2、使用osThreadCreate创建三个任务
两个任务Sender1、Sender2负责将数据写入队列,一个任务Seceiver从队列中取出数据。

// 路径:项目\Core\Src\freertos.c
// 全局变量
osThreadId Sender1_Handle;
osThreadId Sender2_Handle;
osThreadId Seceiver_Handle;if ( g_xQueue != NULL ){// 创建两个任务,传入参数100,200osThreadDef(Sender1, vSendTask, osPriorityNormal, 0, 1000);Sender1_Handle = osThreadCreate(osThread(Sender1), (void *)100);if( Sender1_Handle != NULL ){printf("Succeeded in creating Sender1_Handle Queue. Procedure!\n\r");}else{printf("Fail in creating Sender1_Handle Queue. Procedure!\n\r");}osThreadDef(Sender2, vSendTask, osPriorityNormal, 0, 100);Sender2_Handle = osThreadCreate(osThread(Sender2), (uint32_t *)200);if( Sender2_Handle != NULL ){printf("Succeeded in creating Sender2_Handle Queue. Procedure!\n\r");}else{printf("Fail in creating Sender2_Handle Queue. Procedure!\n\r");}osThreadDef(Seceiver, vSeceiverTask, osPriorityHigh, 0, 1000);Seceiver_Handle = osThreadCreate(osThread(Seceiver), NULL);        if( Seceiver_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;
}

注:Sender1、Sender2任务函数共用一个。

3、Sender1、Sender2 任务函数vSendTask 实现
Sender1、Sender2负责将数据写入队列。由于两个任务使用一个任务处理函数,因此在处理函数内部要先区分当前运行的是哪任务,这里使用任务句柄:每个任务在创建时都会返回一个任务句柄( TaskHandle_t ),这个句柄可以用来唯一标识一个任务。可以在任务函数中使用 xTaskGetCurrentTaskHandle() 函数获取当前任务的句柄,然后与已知的任务句柄进行比较。
pcTaskGetTaskName() 函数来获取当前任务的名称。这个名称是在任务创建时指定的,因此可以用来区分不同的任务。

void vSendTask(void const * argument)
{/* USER CODE BEGIN StartDefaultTask */BaseType_t xReturn = pdPASS;   /* 定义一个创建信息返回值,默认为pdPASS */int32_t lValueToSend;/* Infinite loop */for(;;){/* 根据任务句柄执行不同的任务逻辑,也可以使用参数传入的方式区分任务 */TaskHandle_t xTaskHandle = xTaskGetCurrentTaskHandle();  /* 获取当前任务名称 */const char *pcTaskName = pcTaskGetName(xTaskHandle);lValueToSend = ( int32_t ) argument;xReturn = xQueueSend( g_xQueue, &lValueToSend, 0 ); if (pdPASS == xReturn)printf("DWB Sent SUCCESS ---> %s Message %d sent successfully! \n\r",pcTaskName ,(uint32_t)argument);elseprintf("DWB Sent FAIL ---> %s Message %d sent Fail! \n\r",pcTaskName, (uint32_t)argument);vTaskDelay(pdMS_TO_TICKS(600));   // 延时600ms}    
}

在这个示例中, 使用 xTaskGetCurrentTaskHandle() 来获取当前任务的句柄,然后调用 pcTaskGetTaskName() 来获取任务名称,并将其打印出来。这样,每次任务执行时,都会打印出当前是哪个任务在运行。
注, pcTaskGetTaskName() 函数需要FreeRTOS的配置宏 configUSE_TRACE_FACILITY 被定义为1,以便启用任务跟踪和任务名称的功能。如果你的FreeRTOS配置没有启用这个宏,你需要先在FreeRTOSConfig.h中定义它。

多个任务使用一个任务函数,在任务函数中还可以使用下面几个方法实现

  1. 使用任务优先级:如果每个任务的优先级不同,可以在任务函数中通过 uxTaskPriorityGet(NULL) 获取当前任务的优先级,然后根据优先级执行不同的逻辑。
  2. 使用全局变量:可以定义一个全局变量数组,每个元素对应一个任务的状态或标识。在任务函数中,根据任务的某种标识访问对应的全局变量。
  3. 使用静态变量:在任务函数内部定义静态变量,每个任务实例都会有自己的静态变量副本,可以用来存储任务特定的信息。
  4. 使用事件组:如果任务需要根据事件来执行不同的逻辑,可以使用事件组( EventGroupHandle_t )来区分不同的事件,并在任务函数中根据事件执行相应的操作。
  5. 使用任务通知:通过发送和接收任务通知( vTaskNotifyGive() 和 ulTaskNotifyTake() ),任务可以在接收到特定通知时执行不同的逻辑。

4、Seceiver任务函数 vSeceiverTask实现
任务Seceiver从队列中取出数据。

void vSeceiverTask(void const * argument)
{BaseType_t xReturn = pdTRUE;   /* 定义一个创建信息返回值,默认为pdTRUE */uint32_t r_queue; /* 定义一个接收消息的变量 */const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );for(;;){xReturn = xQueueReceive( g_xQueue, &r_queue, xTicksToWait);      // 获取队列值         if (pdTRUE == xReturn)printf("DWB Receive SUCCESS ---> The data received is %d. \n",(uint32_t)r_queue);elseprintf("DWB Receive FAIL ---> Data reception error, error code :%ld. \n\r",xReturn);vTaskDelay(pdMS_TO_TICKS(500));   // 延时500ms}    
}

三、结果演示

通过串口工具查看,任务读写队列情况
在这里插入图片描述


四、代码下载

[FreeRTOS ] 互斥访问与回环队列 功能应用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/357178.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“论微服务架构及其应用”写作框架,软考高级,系统架构设计师

论文真题 论微服务架构及其应用近年来,随着互联网行业的迅猛发展,公司或组织业务的不断扩张,需求的快速变化以及用户量的不断增加,传统的单块(Monolithic)软件架构面临着越来越多的挑战,已逐渐…

关于DrawTools的分析- 一个优秀的C#开源绘图软件

国外大佬,曾经写过两个关于DrawTools相关的开源绘图软件。 我更新了一个优化的版本如下图,稍后会发布更新给大家。 需要的用户可发邮件给我 448283544qq.com 应用于AGV地图编辑器如下: 那么这个优于很多普通的画布软件,包含点、…

STM32项目分享:家庭环境监测系统

目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 1.PCB图 2.PCB板打样焊接图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片: 哔哩哔哩视频链接: https://www.bilibili.…

系统架构师概述

引言 系统架构设计师是项目开发活动中的众多角色之一,它可以是一个小组或者一个人或者是一个团队,架构师包含建筑师,设计师,创造者,缔造者,可以说架构师就是我们社会各个领域的创造者和缔造者。从组织上划分…

【OS基础】符合AUTOSAR标准的RTAOS-Alarms详解

目录 前言 正文 7.报警Alarms 7.1配置Alarms 7.1.1激活一个任务 7.1.2 设置一个事件 7.1.3报警回调Alarm Callback 7.1.4 增加计数器值 7.2设置Alarms 7.2.1 绝对Alarms 7.2.2 相对Alarm 7.3自启动Alarms 7.4 删除Alarms 7.5确认何时会发生Alarm 7.6非周期Alarm…

Golang | Leetcode Golang题解之第179题最大数

题目&#xff1a; 题解&#xff1a; func largestNumber(nums []int) string {sort.Slice(nums, func(i, j int) bool {x, y : nums[i], nums[j]sx, sy : 10, 10for sx < x {sx * 10}for sy < y {sy * 10}return sy*xy > sx*yx})if nums[0] 0 {return "0"…

网络安全-如何设计一个安全的API(安全角度)

目录 API安全概述设计一个安全的API一个基本的API主要代码调用API的一些问题 BasicAuth认证流程主要代码问题 API Key流程主要代码问题 Bearer auth/Token auth流程 Digest Auth流程主要代码问题 JWT Token流程代码问题 Hmac流程主要代码问题 OAuth比较自定义请求签名身份认证&…

Golang | Leetcode Golang题解之第167题两数之和II-输入有序数组

题目&#xff1a; 题解&#xff1a; func twoSum(numbers []int, target int) []int {low, high : 0, len(numbers) - 1for low < high {sum : numbers[low] numbers[high]if sum target {return []int{low 1, high 1}} else if sum < target {low} else {high--}}r…

示例:WPF中应用Grid的SharedSizeGroup设置整齐的布局

一、目的&#xff1a;应用Grid的SharedSizeGroup设置整齐的布局 二、实现 <ItemsControl ItemsSource"{local:GetStudents Count5}"><ItemsControl.ItemTemplate><DataTemplate><Grid ShowGridLines"True"><Grid.ColumnDefinit…

51单片机STC89C52RC——3.1 数码管静态展示

目的 让数码管在指定位置显示指定数字 一&#xff0c;STC单片机模块 二&#xff0c;数码管 2.1 数码管位置 2.2 生活中用到的数目管 红绿灯 LED数码管在生活中随处可见&#xff0c;洗衣机、电饭煲、热水器、微波炉、冰箱、这些最基本的家用电器上基本都用到了这种7段LED数…

[手机Linux PostmarketOS]一,1加6T真正的手机Linux系统

前面用Linux deploy软件安装了Linux系统在手机&#xff0c;实则不是真正的手机刷成了linux系统&#xff0c;而是通过Linux deploy软件在容器里安装了Linux系统&#xff0c;在使用方面会有诸多限制&#xff0c;并不能发挥Linux的真实强大之处&#xff0c;于是我又百度又谷歌(真不…

51单片机STC89C52RC——5.1 LCD1602液晶显示屏

目录 目的 一&#xff0c;STC单片机模块 二&#xff0c;LCD1602 2.1 模块简介 2.2 针脚 2.3 DDRAM地址与显示器对应关系 2.4 标准字库表 2.5 常用指令 2.6 读写操作 三&#xff0c;创建Keil项目 四&#xff0c;代码 五&#xff0c;代码编译、下载到51单片机 六&a…

掌握Three.js:学习路线,成为3D可视化开发的高手!

学习Three.js可以按照以下路线进行&#xff1a; 基础知识&#xff1a; 首先要了解基本的Web开发知识&#xff0c;包括HTML、CSS和JavaScript。如果对这些知识已经比较熟悉&#xff0c;可以直接进入下一步。 Three.js文档&#xff1a; 阅读Three.js官方文档是学习的第一步。官…

【Flutter 专题】120 Flutter 腾讯移动通讯 TPNS~

1.2 方法使用 小菜按照官网的介绍尝试了一些常用的 API 方式&#xff0c;主要分为应用类&#xff0c;账号类和标签类三种 API&#xff0c;小菜业务中没有应用账号和标签模块&#xff0c;暂未深入研究&#xff1b; 应用接口 API a. 注册推送服务 对于服务的注册初始化&#x…

跟TED演讲学英文:How language shapes the way we think by Lera Boroditsky

How language shapes the way we think Link: https://www.ted.com/talks/lera_boroditsky_how_language_shapes_the_way_we_think? Speaker: Lera Boroditsky Date: November 2017 文章目录 How language shapes the way we thinkIntroductionVocabularySummaryTranscriptA…

目前哪个充电宝品牌比较好?四款优质充电宝分享

在电量成为现代生活不可或缺的生产资源的时代&#xff0c;选择一款优质的充电宝无疑是保证移动设备持续运作的关键。面对市场上众多品牌和型号的充电宝&#xff0c;消费者在选择时可能会感到困惑和迷茫。本文将为您揭示哪些品牌真正代表了耐用性和质量的典范&#xff0c;让自己…

贪心算法—

贪心算法是一种在每一步选择中都采取在当前状态下最好或最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望导致结果是全局最好或最优的算法。这种算法并不总是能找到全局最优解&#xff0c;但在某些问题上能提供足够好的解决方案。贪心算法的关键特性包括&#…

51单片机STC89C52RC——6.1 中断系统

一&#xff0c;文字层面理解 反正我看下面的几段文字时脑壳没有正常运转。一个头几个大 中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。 当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求&#xff0c;要求CPU暂停当前的工作&#xff0c;转而去处理这…

华为---- RIP路由协议基本配置

08、RIP 8.1 RIP路由协议基本配置 8.1.1 原理概述 RIP(Routing Information Protocol,路由协议)作为最早的距离矢量IP路由协议&#xff0c;也是最先得到广泛使用的一种路由协议&#xff0c;采用了Bellman-Ford算法&#xff0c;其最大的特点就是配置简单。 RIP协议要求网络中…

使用Gradle查看Android项目中库的依赖关系

| | -- com.android.support:support-compat:25.3.1 | | | — com.android.support:support-annotations:25.3.1 | | -- com.android.support:support-media-compat:25.3.1 | | | -- com.android.support:support-annotations:25.3.1 | | | — com.android.support:support…