【FreeRTOS】任务状态改进播放控制

2024-06-23 11:04

本文主要是介绍【FreeRTOS】任务状态改进播放控制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这里写目录标题

  • 1 任务状态
    • 1.1 阻塞状态(Blocked)
    • 1.2 暂停状态(Suspended)
    • 1.3 就绪状态(Ready)
    • 1.4 完整的状态转换图
  • 2 举个例子
  • 3 编写代码


在这里插入图片描述

参考《FreeRTOS入门与工程实践(基于DshanMCU-103).pdf》

本节课实现音乐任务的创建,音乐播放的暂停与继续播放,删除任务。

代码为:08_task_priority

重点:使用链表讲解内部原理。

  • 任务状态:09_task_suspend,添加音乐暂停/恢复功能
  • 优先级、链表管理
  • 任务切换、tick

1 任务状态

以前我们很简单地把任务的状态分为两种:运行(Runing)、非运行(Not Running)。 对于非运行的状态,还可以继续细分,比如前面的FreeRTOS_04_task_priority中:

  • Task3执行vTaskDelay后:处于非运行状态,要过3秒种才能再次运行
  • Task3运行期间,Task1、Task2也处于非运行状态,但是它们随时可以运行
  • 这两种"非运行"状态就不一样,可以细分为:
  • 阻塞状态(Blocked)
  • 暂停状态(Suspended)
  • 就绪状态(Ready)

1.1 阻塞状态(Blocked)

在日常生活的例子中,母亲在电脑前跟同事沟通时,如果同事一直没回复,那么母亲的工作就被卡住了、被堵住了、处于阻塞状态(Blocked)。重点在于:母亲在等待。

在FreeRTOS_04_task_priority实验中,如果把任务3中的vTaskDelay调用注释掉,那么任务1、任务2根本没有执行的机会,任务1、任务2被"饿死"了(starve)。

在实际产品中,我们不会让一个任务一直运行,而是使用"事件驱动"的方法让它运行:

  • 任务要等待某个事件,事件发生后它才能运行
  • 在等待事件过程中,它不消耗CPU资源
  • 在等待事件的过程中,这个任务就处于阻塞状态(Blocked)

在阻塞状态的任务,它可以等待两种类型的事件:

  • 时间相关的事件
    • 可以等待一段时间:我等2分钟
    • 也可以一直等待,直到某个绝对时间:我等到下午3点
  • 同步事件:这事件由别的任务,或者是中断程序产生
    • 例子1:任务A等待任务B给它发送数据
    • 例子2:任务A等待用户按下按键
    • 同步事件的来源有很多(这些概念在后面会细讲):
      • 队列(queue)
      • 二进制信号量(binary semaphores)
      • 计数信号量(counting semaphores)
      • 互斥量(mutexes)
      • 递归互斥量、递归锁(recursive mutexes)
      • 事件组(event groups)
      • 任务通知(task notifications)

在等待一个同步事件时,可以加上超时时间。比如等待队里数据,超时时间设为10ms:

  • 10ms之内有数据到来:成功返回
  • 10ms到了,还是没有数据:超时返回

1.2 暂停状态(Suspended)

在日常生活的例子中,母亲正在电脑前跟同事沟通,母亲可以暂停:

  • 好烦啊,我暂停一会
  • 领导说:你暂停一下

FreeRTOS中的任务也可以进入暂停状态,唯一的方法是通过vTaskSuspend函数。函数原型如下:

void vTaskSuspend( TaskHandle_t xTaskToSuspend );

参数xTaskToSuspend表示要暂停的任务,如果为NULL,表示暂停自己。

要退出暂停状态,只能由别人来操作:

  • 别的任务调用:vTaskResume
  • 中断程序调用:xTaskResumeFromISR

实际开发中,暂停状态用得不多。

1.3 就绪状态(Ready)

这个任务完全准备好了,随时可以运行:只是还轮不到它。这时,它就处于就绪态(Ready)。

1.4 完整的状态转换图

完整的状态转换图如下:

在这里插入图片描述


2 举个例子

任务的状态:Ready状态(就绪)和 Running状态(运行)

在这里插入图片描述

现在给小孩喂饭,这个就处于Running状态,回复信息就处于Ready状态,随时可以切换过去
当回复信息时候,这个就处于Running状态,给小孩喂饭就处于Ready状态

Ready状态随时有机会切换为Running状态,只要有机会运行,就称为Running状态,当Running状态被调度出去后,就成了Ready状态

还有其他状态,Blocked(被阻塞,在等待某些event事件),suspend(暂停状态,单纯的不想干活,就只想休息)

在这里插入图片描述
创建播放音乐的任务,这个任务创建好后,就处于Ready状态,这个任务的优先级最高,能运行的时候,它就处于Running状态,当调用vTaskDelay的时候,就处于Blocked状态(等待某些事件)

在这里插入图片描述
当时间到了,就会被唤醒,就变成Ready就绪状态,当能运行的时候,就变成Running状态

suspend暂停状态只能调用vTaskSuspend函数进入

  • 可以自己调用vTaskSuspend进入,也可以别人调用vTaskSuspend函数
    在这里插入图片描述

3 编写代码

编写代码实现功能:第一次按下播放按键,创建音乐播放任务,再次按下播放按键,暂停音乐播放,再次按下播放按键,恢复音乐播放,按power按键,删除音乐播放任务

工程:09_task_suspend

在默认任务里修改代码,如下:

/*** @brief  Function implementing the defaultTask thread.* @param  argument: Not used* @retval None*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */uint8_t dev, data;int len;uint8_t status;     //状态变量uint8_t bRunning;   //是不是正在运行BaseType_t ret; // longTaskHandle_t xSoundTaskHandle = NULL;           // 句柄 初始值是NULL	  LCD_Init();LCD_Clear();IRReceiver_Init();LCD_PrintString(0, 0, "Waiting Control");while (1)   // 在屏幕上输出接收到的键值{/* 读取红外遥控器 */if (0 == IRReceiver_Read(&dev, &data)){if (data == 0x22)   /*play*/{/* 创建播放音乐的任务 *///这里需要判断是否多次按下播放按键,判断句柄是否等于NULLif (xSoundTaskHandle == NULL)   /* 句柄等于NULL,才来创建这个任务 */{LCD_ClearLine(0, 0);    //清屏LCD_PrintString(0, 0, "Create Task");ret = xTaskCreate(PlayMusic, "SoundTask", 128, NULL, osPriorityNormal+1, &xSoundTaskHandle);bRunning = 1;   //正在运行。等于1}else{/* 要么suspend,要么resume恢复它 */if (bRunning)   //如果bRunning == 1{LCD_ClearLine(0, 0);    //清屏LCD_PrintString(0, 0, "Suspend Task");vTaskSuspend(xSoundTaskHandle);     // 如果任务正在运行,就将任务切换成suspend状态PassiveBuzzer_Control(0);           // Stop Buzzer 停止蜂鸣器,清除噪音bRunning = 0;}else{LCD_ClearLine(0, 0);    //清屏LCD_PrintString(0, 0, "Resume Task");vTaskResume(xSoundTaskHandle);     // 如果任务Suspend,就将任务vTaskResume,恢复bRunning = 1;}}}else if (data == 0xA2){/* 删除播放音乐的任务 */if (xSoundTaskHandle != NULL)   //如果这个句柄xSoundTaskHandle != NULL,才会删除{LCD_ClearLine(0, 0);    //清屏LCD_PrintString(0, 0, "Delete Task");vTaskDelete(xSoundTaskHandle);PassiveBuzzer_Control(0);   // Stop Buzzer 停止蜂鸣器xSoundTaskHandle = NULL;    //删除完成,赋值NULL}}len = LCD_PrintString(0, 6, "Key name: ");LCD_PrintString(len, 6, IRReceiver_CodeToString(data));}}/* USER CODE END StartDefaultTask */
}

在这里插入图片描述

这篇关于【FreeRTOS】任务状态改进播放控制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1086970

相关文章

(超详细)YOLOV7改进-Soft-NMS(支持多种IoU变种选择)

1.在until/general.py文件最后加上下面代码 2.在general.py里面找到这代码,修改这两个地方 3.之后直接运行即可

YOLOv8改进 | SPPF | 具有多尺度带孔卷积层的ASPP【CVPR2018】

💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 专栏目录 :《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进——点击即可跳转 Atrous Spatial Pyramid Pooling (ASPP) 是一种在深度学习框架中用于语义分割的网络结构,它旨

Java研学-RBAC权限控制(八)

九 登录登出 1 登录作用   判断员工是否有权限访问,首先得知道现在操作的人是谁,所以必须先实现登录功能 2 登录流程   ① 提供登录页面,可输入用户名与密码信息,并添加执行登录的按钮。(登录页面不能被拦截)   ② 给按钮绑定点击事件(异步操作,POST请求)   ③ 事件中发送登录请求,使用 AJAX 方式提交。(使用 AJAX 原因:用户体验更好,既可保留用户刚输入的用户名和密码

如何设置windows计划任务

如何设置windows计划任务 前言:在工作过程中写了一个python脚本,用于调用jira接口查询bug单数量,想要在本地定时任务执行,每天发送到钉钉群提醒,写下操作步骤用于记录。 1. 准备 Python 脚本 确保你的 Python 脚本已经保存到一个文件,比如 jira_reminder.py。 2. 创建批处理文件 为了方便任务计划程序运行 Python 脚本,创建一个批处理文

ROS2从入门到精通4-4:局部控制插件开发案例(以PID算法为例)

目录 0 专栏介绍1 控制插件编写模板1.1 构造控制插件类1.2 注册并导出插件1.3 编译与使用插件 2 基于PID的路径跟踪原理3 控制插件开发案例(PID算法)常见问题 0 专栏介绍 本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。 🚀详情:《ROS2从入门到精通》 1 控制插

MQTT之CONNECT控制报文详解

目录 1.  MQTT协议规范 2.  名词解释 3.  CONNECT控制报文详解 3.1  固定报头 Fixed header 3.2  可变报头 Variable header 3.2.1  协议名 Protocol Name 3.2.2  协议级别 Protocol Level 3.2.3  连接标志 Connect Flags 3.2.4  保持连接 Keep

HTTP状态码中301与302的区别

一.官方说法  301,302 都是HTTP状态的编码,都代表着某个URL发生了转移,不同之处在于:  301 redirect: 301 代表永久性转移(Permanently Moved)。  302 redirect: 302 代表暂时性转移(Temporarily Moved )。  这是很官方的说法,那么它们的区别到底是什么呢?  1.1、什么是301转向?什么是301重定向?

STM32单片机PWR电源控制详解

文章目录 1. PWR概述 2. 电源结构框图 3. 上电复位和掉电复位 4. 可编程电压监测器 5. 低功耗模式 6. 模式选择 6.1 睡眠模式 6.2 停止模式 6.3 待机模式 7. 代码示例 1. PWR概述 PWR(Power Control)电源控制,负责管理STM32内部的电源供电部分,可以实现可编程电压监测器和低功耗模式的功能。 可编程电压监测器

Zustand 状态管理库简介

1. Zustand 简介 Zustand(德语中意为“状态”)是一个使用简单 API 的 React 状态管理库。它的核心思想是以状态切片(slices)的方式组织应用状态,从而实现高效的状态管理。Zustand 提供了比 Redux 更加简洁和直接的用法,同时支持异步操作和中间件。 在React开发中,状态管理是一个非常重要的概念。虽然 React 提供了 useState 和 useRe

基于动力学的六自由度机器人阻抗恒力跟踪控制

1.整个代码的控制流程图如下: 2.正逆运动学计算 略 3.动力学模型 采用拉格朗日法计算机械臂的动力学模型,其输入的是机械臂的关节角度、角速度和角加速度;其中M、C、G本别是计算的惯性力、科式力和重力项,相关部分如下: 4.RBF神经网络自适应参数调节 采用RBF自适应调节阻抗控制器参数,末端每个方向单独进行参数的调整,其中rbf的输入的是力和位置,输出的是阻抗控制器的参数,rb