任务挂起和恢复

news2025/4/5 11:24:17

任务挂起和恢复API函数

下面用按键和震动传感器验证任务挂起和恢复API函数:

PA7接震动传感器,按键引脚为PA0,提前初始化好GPIO引脚

key.c

#include "key.h"
#include "stm32f10x.h"


void KeyInit()
{
   GPIO_InitTypeDef  KeyInitSruct;
	
	
   RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE);
   	

    KeyInitSruct.GPIO_Mode = GPIO_Mode_IPU;
	KeyInitSruct.GPIO_Pin = GPIO_Pin_7;
	GPIO_Init(GPIOA,&KeyInitSruct);


    KeyInitSruct.GPIO_Mode = GPIO_Mode_IPU;
	KeyInitSruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_Init(GPIOA,&KeyInitSruct);

}

main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
#include "key.h"



//开始任务
#define START_TASK_SIZE 256
#define START_TASK_PRIO 1
StackType_t  StartTaskStack[START_TASK_SIZE];
StaticTask_t StartTask_TCB;
TaskHandle_t StartTask_Handle;
void start_task( void * pvParameters );

//任务1
#define TASK1_TASK_SIZE 120
#define TASK1_TASK_PRIO 4
StackType_t  Task1TaskStack[TASK1_TASK_SIZE];
StaticTask_t Task1Task_TCB;
TaskHandle_t Task1Task_Handle;
void task1_task( void * pvParameters );

//任务2
#define TASK2_TASK_SIZE 120
#define TASK2_TASK_PRIO 3
StackType_t  Task2TaskStack[TASK2_TASK_SIZE];
StaticTask_t Task2Task_TCB;
TaskHandle_t Task2Task_Handle;
void task2_task( void * pvParameters );

//任务3
#define KEY_TASK_SIZE 120
#define KEY_TASK_PRIO 2
StackType_t  KeyaskStack[KEY_TASK_SIZE];
StaticTask_t KeyTask_TCB;
TaskHandle_t KeyTask_Handle;
void key_task( void * pvParameters );

//空闲任务
static StaticTask_t IdleTaskTCB;
static StackType_t  IdleTaskStack[configMINIMAL_STACK_SIZE];

   void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
                                       StackType_t ** ppxIdleTaskStackBuffer,
                                       uint32_t * pulIdleTaskStackSize )
	 {
	    
	      *ppxIdleTaskTCBBuffer = &IdleTaskTCB;
		    *ppxIdleTaskStackBuffer = IdleTaskStack;
		    *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
	 
	 }

//定时器任务
static StaticTask_t TimerTaskTCB;
static StackType_t  TimerTaskStack[configTIMER_TASK_STACK_DEPTH];
	 
 void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
                                      StackType_t ** ppxTimerTaskStackBuffer,
                                      uint32_t * pulTimerTaskStackSize )
 {
 
      * ppxTimerTaskTCBBuffer = &TimerTaskTCB;
	    * ppxTimerTaskStackBuffer = TimerTaskStack;
      *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
 
 }

	 
	 
	 
int main(void)
{

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 
	delay_init();	    				//延时函数初始化	  
	uart_init(115200);					//串口初始化
	LED_Init();		  					//LED初始化
	KeyInit();               //引脚初始化
	
	StartTask_Handle =  xTaskCreateStatic( (TaskFunction_t) start_task,
                                  (char * )        "start_task", 
                                  (uint32_t)       START_TASK_SIZE,
                                  (void *)         NULL,
                                  (UBaseType_t)    START_TASK_PRIO,
                                  (StackType_t *)  StartTaskStack,
                                  (StaticTask_t *) &StartTask_TCB );
  
        vTaskStartScheduler();          //开启任务调度
}
//开始任务
void start_task( void * pvParameters )
{
   while(1)
	 {
		 //任务1
	   Task1Task_Handle =  xTaskCreateStatic( (TaskFunction_t) task1_task,
                                  (char * )        "task1_task", 
                                  (uint32_t)       TASK1_TASK_SIZE,
                                  (void *)         NULL,
                                  (UBaseType_t)    TASK1_TASK_PRIO,
                                  (StackType_t *)  Task1TaskStack,
                                  (StaticTask_t *) &Task1Task_TCB );
																	
		//任务2													
	   Task2Task_Handle =  xTaskCreateStatic( (TaskFunction_t) task2_task,
                                  (char * )        "task2_task", 
                                  (uint32_t)       TASK2_TASK_SIZE,
                                  (void *)         NULL,
                                  (UBaseType_t)    TASK2_TASK_PRIO,
                                  (StackType_t *)  Task2TaskStack,
                                  (StaticTask_t *) &Task2Task_TCB );
																	
			//任务3											
	   KeyTask_Handle =  xTaskCreateStatic( (TaskFunction_t) key_task,
                                  (char * )        "key_task", 
                                  (uint32_t)       KEY_TASK_SIZE,
                                  (void *)         NULL,
                                  (UBaseType_t)    KEY_TASK_PRIO,
                                  (StackType_t *)  KeyaskStack,
                                  (StaticTask_t *) &KeyTask_TCB );														
	    
	       vTaskDelete(StartTask_Handle);
	 }
	
}
//任务1
void task1_task( void * pvParameters )
{
   char Task1_num = 0;
while(1)
{
   Task1_num++;
   LED2 = !LED2;
	 vTaskDelay(1000);
	printf("Task1 is Runing %d \r\n",Task1_num);

}

}
//任务2
void task2_task( void * pvParameters )
{ 
	char Task2_num = 0;
while(1)
{
   Task2_num++;
   LED3 = !LED3;
	 vTaskDelay(1000);
   printf("Task2 is Runing %d \r\n",Task2_num);

}


}

//任务3
void key_task( void * pvParameters )
{ 
	
while(1)
{
      if( GPIO_ReadInputDataBit(GPIOA,  GPIO_Pin_7) == 0)

			{ 
			      vTaskDelay(100);
				  vTaskSuspend(Task1Task_Handle);//当震动传感器工作将任务1挂起
				  printf("Task1 is Suspend!   \r\n");
			    
			}
			
			 if( GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0)

			{ 
			    vTaskDelay(100);
				  vTaskResume(Task1Task_Handle);//当按键按下将任务1解挂
				  printf("Task1 is Resume!   \r\n");
			    
			}
			  

}


}

下面用串口验证:

下面我们在中断服务函数中恢复任务1

xTaskResumeFromISR();该函数的参数依旧是任务句柄,但是该函数有两个返回值

返回值:
pdTRUE:    恢复运行的任务的任务优先级等于或者高于正在运行的任务(被中断打    
断的任务),这意味着在退出中断服务函数以后必须进行一次上下文切换。
pdFALSE:    恢复运行的任务的任务优先级低于当前正在运行的任务(被中断打断的    
任务),这意味着在退出中断服务函数的以后不需要进行上下文切换。

修改main.c:当震动传感器工作将任务1挂起

//任务3
void key_task( void * pvParameters )
{ 
	
while(1)
{
      if( GPIO_ReadInputDataBit(GPIOA,  GPIO_Pin_7) == 0)

			{ 
			    vTaskDelay(100);
				  vTaskSuspend(Task1Task_Handle);
				  printf("Task1 is Suspend!   \r\n");
			    
			}
			
					 
}


}

exti.c:

#include "exti.h"
#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"
#include "delay.h"

void EXTIInit(void)
{

	EXTI_InitTypeDef Exti_Initstruct;
	NVIC_InitTypeDef NVIC_Initstruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

	
	Exti_Initstruct.EXTI_Line = EXTI_Line0;
	Exti_Initstruct.EXTI_LineCmd = ENABLE;
	Exti_Initstruct.EXTI_Mode = EXTI_Mode_Interrupt;
	Exti_Initstruct.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_Init(&Exti_Initstruct);
	
	NVIC_Initstruct.NVIC_IRQChannel = EXTI0_IRQn;
	NVIC_Initstruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Initstruct.NVIC_IRQChannelPreemptionPriority = 6;//定义抢占优先级为6,小于5的中断不受FreeRtos管控!
	NVIC_Initstruct.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&NVIC_Initstruct);

}
 
 
extern TaskHandle_t Task1Task_Handle;

void EXTI0_IRQHandler()//外部中断函数
{
	BaseType_t YieldRequired;

	delay_xms(20);//消抖

    if ( EXTI_GetITStatus(EXTI_Line0) != RESET)    //检测中断标志位
		{
		     YieldRequired = xTaskResumeFromISR(Task1Task_Handle);//恢复任务1

			   printf("恢复任务1的运行! \r\n");

			if(YieldRequired == pdTRUE)//如果函数返回值是pdTRUE,进行一次上下文切换
			{
			  portYIELD_FROM_ISR(YieldRequired);//上下文切换函数
			}
			
		
		}			
   EXTI_ClearITPendingBit(EXTI_Line0);//清除中断

}








下面用串口验证结果:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【NLP 55、投机采样加速推理】

目录 一、投机采样 二、投机采样改进:美杜莎模型 流程 改进 三、Deepseek的投机采样 流程 Ⅰ、输入文本预处理 Ⅱ、引导模型预测 Ⅲ、候选集筛选(可选) Ⅳ、主模型验证 Ⅴ、生成输出与循环 骗你的,其实我在意透了 —— 25.4.4 一、…

如何在 Windows 上安装 Python

Python是一种高级编程语言,由于其简单性、多功能性和广泛的应用范围而变得越来越流行。如何在 Windows 操作系统中安装 Python 的过程相对简单,只需几个简单的步骤。 本文旨在指导您完成在 Windows 计算机上下载和安装 Python 的过程。 如何在 Windows…

selectdb修改表副本

如果想修改doris(也就是selectdb数据库)表的副本数需要首先确定是否分区表,当前没有数据字典得知哪个表是分区的,只能先show partitions看结果 首先,副本数不应该大于be节点数 其次,修改期间最好不要跑业务…

Metabase:一个免费开源的BI平台

今天给大家介绍一个开源数据可视化分析工具:Metabase。它可以帮助用户快速连接数据库、执行查询并创建交互式仪表盘,即使非技术人员也能快速上手。 Metabase 支持多种数据源,包括 MySQL、PostgreSQL、Oracle、SQL Server、SQLite、MongoDB、P…

第15届蓝桥杯省赛python组A,B,C集合

过几天就省赛了,一直以来用的是C,Python蓝桥杯也是刚刚开始准备(虽然深度学习用的都是python,但是两者基本没有任何关系),这两天在做去年题时犯了很多低级错误,因此记录一下以便自己复查 PS&am…

为什么有的深度学习训练,有训练集、验证集、测试集3个划分,有的只是划分训练集和测试集?

在机器学习和深度学习中,数据集的划分方式取决于任务需求、数据量以及模型开发流程的严谨性。 1. 三者划分:训练集、验证集、测试集 目的 训练集(Training Set):用于模型参数的直接训练。验证集(Validati…

虚拟现实 UI 设计:打造沉浸式用户体验

VR UI 设计基础与特点 虚拟现实技术近年来发展迅猛,其独特的沉浸式体验吸引了众多领域的关注与应用。在 VR 环境中,UI 设计扮演着至关重要的角色,它是用户与虚拟世界交互的桥梁。与传统 UI 设计相比,VR UI 设计具有显著的特点。传…

前端Uniapp接入UviewPlus详细教程!!!

相信大家在引入UviewPlusUI时遇到很头疼的问题,那就是明明自己是按照官网教程一步一步的走,为什么到处都是bug呢?今天我一定要把这个让人头疼的问题解决了! 1.查看插件市场 重点: 我们打开Dcloud插件市场搜素uviewPl…

【性能优化点滴】odygrd/quill在编译期做了哪些优化

Quill 是一个高性能的 C 日志库,它在编译器层面进行了大量优化以确保极低的运行时开销。以下是 Quill 在编译器优化方面的关键技术和实现细节: 1. 编译时字符串解析与格式校验 Quill 在编译时完成格式字符串的解析和校验,避免运行时开销&…

02 反射 泛型(II)

目录 一、反射 1. 反射引入 2. 创建对象 3. 反射核心用法 二、泛型 1. 泛型的重要性 (1)解决类型安全问题 (2)避免重复代码 (3)提高可读性和维护性 2. 泛型用法 (1)泛型类 …

元宇宙浪潮下,前端开发如何“乘风破浪”?

一、元宇宙对前端开发的新要求 元宇宙的兴起,为前端开发领域带来了全新的挑战与机遇。元宇宙作为一个高度集成、多维互动的虚拟世界,要求前端开发不仅具备传统网页开发的能力,还需要掌握虚拟现实(VR)、增强现实&#…

2025年3月 Scratch 图形化(二级)真题解析 中国电子学会全国青少年软件编程等级考试

2025.03Scratch图形化编程等级考试二级真题试卷 一、选择题 第 1 题 甲、乙、丙、丁、戊五人参加100米跑比赛,甲说:“我的前面至少有两人,但我比丁快。”乙说:“我的前面是戊。”丙说:“我的后面还有两个人。”请从前往后(按照速度快慢&a…

从代码学习深度学习 - GRU PyTorch版

文章目录 前言一、GRU模型介绍1.1 GRU的核心机制1.2 GRU的优势1.3 PyTorch中的实现二、数据加载与预处理2.1 代码实现2.2 解析三、GRU模型定义3.1 代码实现3.2 实例化3.3 解析四、训练与预测4.1 代码实现(utils_for_train.py)4.2 在GRU.ipynb中的使用4.3 输出与可视化4.4 解析…

二叉树 递归

本篇基于b站灵茶山艾府的课上例题与课后作业。 104. 二叉树的最大深度 给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1: 输入:root [3,9,20,null,null,15,7] 输出&…

反常积分和定积分的应用 2

世界尚有同类 前言伽马函数的推论关于数学的思考平面图形的面积笛卡尔心形线伯努利双纽线回顾参数方程求面积星型线摆线 旋转体体积一般轴线旋转被积函数有负数部分曲线的弧长最后一个部分内容-旋转曲面侧表面积直角坐标系极坐标系参数方程 总结 前言 力大出奇迹。好好加油。 …

Element-plus弹出框popover,使用自定义的图标选择组件

自定义的图标选择组件是若依的项目的 1. 若依的图标选择组件 js文件,引入所有的svg图片 let icons [] // 注意这里的路径,一定要是自己svg图片的路径 const modules import.meta.glob(./../../assets/icons/svg/*.svg); for (const path in modules)…

思维链 Chain-of-Thought(COT)

思维链 Chain-of-Thought(COT):思维链的启蒙 3. 思维链 Chain-of-Thought(COT)存在问题?2. 思维链 Chain-of-Thought(COT)是思路是什么?1. 什么是 思维链 Chain-of-Thoug…

硬件电路(23)-输入隔离高低电平有效切换电路

一、概述 项目中为了防止信号干扰需要加一些隔离电路,而且有时传感器的信号是高有效有时是低有效,所以基于此背景,设计了一款方便实现高低电平有效检测切换电路。 二、应用电路

大模型学习二:DeepSeek R1+蒸馏模型组本地部署与调用

一、说明 DeepSeek R1蒸馏模型组是基于DeepSeek-R1模型体系,通过知识蒸馏技术优化形成的系列模型,旨在平衡性能与效率。 1、技术路径与核心能力 基础架构与训练方法‌ ‌DeepSeek-R1-Zero‌:通过强化学习(RL)训练&…

相机的曝光和增益

文章目录 曝光增益增益原理主要作用增益带来的影响增益设置与应用 曝光 参考:B站优致谱视觉 增益 相机增益是指相机在拍摄过程中对图像信号进行放大的一种操作,它在提高图像亮度和增强图像细节方面起着重要作用,以下从原理、作用、影响以…