FreeRTOS任务的挂起和恢复

本文详细介绍了在FreeRTOS中如何使用任务挂起(vTaskSuspend)和恢复(vTaskResume)API函数,以及与任务控制块、调度器和优先级的关系。通过示例展示了如何在按键事件中控制任务的暂停和继续执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

任务挂起和任务恢复API函数解析

 

  • 1:根据任务句柄来挂起任务控制块,如果任务句柄为NULL表示要挂起任务自身
  • 2:将要挂起的任务从相应的状态列表中移除
  • 3:判断任务调度器是否在运行,如果在运行,更新下一次阻塞时间,防止被挂起任务为下一次阻塞超时
  • 4:如果挂起的是任务自身 【调度器正在运行,强制进行一次任务切换】,调度器没有运行【是:代表任务均被挂起,则当前的控制块赋值为NULL】【否:通过函数vTaskSwitchContext寻找下一个最高优先级任务】

实现功能简介

 

创建一个头文件进行宏定义和函数声明(TaskHead.h)

#ifndef __TASKHEADE_H_
#define __TASKHEADE_H_

// 任务堆栈深度
#define STACK_TASK_DEPTH   128
// 优先级
#define STACK_TASK_PRIO    1
// 任务句柄
TaskHandle_t TASK_BEGIN_HANDLE;


// 任务堆栈深度
#define KEY_TASK_DEPTH   128
// 优先级
#define KEY_TASK_PRIO    2
// 任务句柄
TaskHandle_t KEY_HANDLE;

// 任务堆栈深度
#define TASK1_TASK_DEPTH   128
// 优先级
#define TASK1_TASK_PRIO    3
// 任务句柄
TaskHandle_t TASK1_HANDLE;

// 任务堆栈深度
#define TASK2_TASK_DEPTH   128
// 优先级
#define TASK2_TASK_PRIO    4
// 任务句柄
TaskHandle_t TASK2_HANDLE;


void start_task(void * pram);
void key_task(void *pram);
void task1(void *pram);
void task2(void *pram);




#endif

使用FreeRTOS动态创建任务

int main(void){
   
	  xTaskCreate( 
	                (TaskFunction_t )             start_task,
                  ( char *        )            "start_task", 
                  (uint16_t       )            STACK_TASK_DEPTH,
                  (void *         )            NULL,
                  (UBaseType_t    )            STACK_TASK_PRIO,
                  (TaskHandle_t * )            &TASK_BEGIN_HANDLE );
					// 开始任务				
					vTaskStartScheduler();				
    while(1){
		
		}
    return 0;

}

start_task任务创建

// 创建开始任务
void start_task(void * pram){
      taskENTER_CRITICAL();           //进入临界区
	    xTaskCreate( 
	                (TaskFunction_t )            key_task,
                  ( char *        )            "key_task", 
                  (uint16_t       )            KEY_TASK_DEPTH,
                  (void *         )            NULL,
                  (UBaseType_t    )            KEY_TASK_PRIO,
                  (TaskHandle_t * )            &KEY_HANDLE );
	   
     	xTaskCreate( 
	                (TaskFunction_t )            task1,
                  ( char *        )            "task1", 
                  (uint16_t       )            TASK1_TASK_DEPTH,
                  (void *         )            NULL,
                  (UBaseType_t    )            TASK1_TASK_PRIO,
                  (TaskHandle_t * )            &TASK1_HANDLE );

     xTaskCreate( 
	                (TaskFunction_t )            task2,
                  ( char *        )            "task2", 
                  (uint16_t       )            TASK2_TASK_DEPTH,
                  (void *         )            NULL,
                  (UBaseType_t    )            TASK2_TASK_PRIO,
                  (TaskHandle_t * )            &TASK2_HANDLE );
    //删除开始时任务
		vTaskDelete(TASK_BEGIN_HANDLE);
		// 退出临界区
		taskEXIT_CRITICAL(); 
									
}

任务实现函数:创建的FreeRTOS任务需要做的事情

// 创建任务函数
void key_task(void *pram){
	 LED_Init();
	 Key_Init();
	 while (1)
	{
		// 直接把函数放在main函数中获取键码值的时候起效果了
		if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)			//按键1按下
		{
			 vTaskDelay(10);     // 延时消除抖动
			 // 将按键挂起
			 vTaskSuspend(TASK1_HANDLE);
		}
		
		if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0)			//按键2按下
		{
			 vTaskDelay(10);    // 延时消除抖动
			 // 将按键唤醒
			 vTaskResume(TASK1_HANDLE);
		}
	}
	vTaskDelay(10);			//延时10ms 
     
}


// 创建任务函数
void task1(void *pram){
	   
	   LED_Init();
     while(1){
		    LED1_Turn();
			  vTaskDelay(30);
		 
		 }
}

// 创建任务函数
void task2(void *pram){
	   LED_Init();
     while(1){
		    LED2_Turn();
			  vTaskDelay(30);
		 
		 }
}

main函数所有代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "freeRTOS.h"
#include "task.h"
#include "LED.h"
#include "TaskHead.h"
#include "KEY.h"


int main(void){
   
	  xTaskCreate( 
	                (TaskFunction_t )             start_task,
                  ( char *        )            "start_task", 
                  (uint16_t       )            STACK_TASK_DEPTH,
                  (void *         )            NULL,
                  (UBaseType_t    )            STACK_TASK_PRIO,
                  (TaskHandle_t * )            &TASK_BEGIN_HANDLE );
					// 开始任务				
					vTaskStartScheduler();				
    while(1){
		
		}
    return 0;

}
// 创建开始任务
void start_task(void * pram){
      taskENTER_CRITICAL();           //进入临界区
	    xTaskCreate( 
	                (TaskFunction_t )            key_task,
                  ( char *        )            "key_task", 
                  (uint16_t       )            KEY_TASK_DEPTH,
                  (void *         )            NULL,
                  (UBaseType_t    )            KEY_TASK_PRIO,
                  (TaskHandle_t * )            &KEY_HANDLE );
	   
     	xTaskCreate( 
	                (TaskFunction_t )            task1,
                  ( char *        )            "task1", 
                  (uint16_t       )            TASK1_TASK_DEPTH,
                  (void *         )            NULL,
                  (UBaseType_t    )            TASK1_TASK_PRIO,
                  (TaskHandle_t * )            &TASK1_HANDLE );

     xTaskCreate( 
	                (TaskFunction_t )            task2,
                  ( char *        )            "task2", 
                  (uint16_t       )            TASK2_TASK_DEPTH,
                  (void *         )            NULL,
                  (UBaseType_t    )            TASK2_TASK_PRIO,
                  (TaskHandle_t * )            &TASK2_HANDLE );
    //删除开始时任务
		vTaskDelete(TASK_BEGIN_HANDLE);
		// 退出临界区
		taskEXIT_CRITICAL(); 
									
}
// 创建任务函数
void key_task(void *pram){
	 LED_Init();
	 Key_Init();
	 while (1)
	{
		// 直接把函数放在main函数中获取键码值的时候起效果了
		if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)			//按键1按下
		{
			 vTaskDelay(10);     // 延时消除抖动
			 // 将按键挂起
			 vTaskSuspend(TASK1_HANDLE);
		}
		
		if (GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0)			//按键2按下
		{
			 vTaskDelay(10);    // 延时消除抖动
			 // 将按键唤醒
			 vTaskResume(TASK1_HANDLE);
		}
	}
	vTaskDelay(10);			//延时10ms 
     
}


// 创建任务函数
void task1(void *pram){
	   
	   LED_Init();
     while(1){
		    LED1_Turn();
			  vTaskDelay(30);
		 
		 }
}

// 创建任务函数
void task2(void *pram){
	   LED_Init();
     while(1){
		    LED2_Turn();
			  vTaskDelay(30);
		 
		 }
}

 两个LED灯产生的PWM波形

当一个按键被按下的时候TASK1任务会被挂起,当按下第二个按键的时候第二个任务会被挂起

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值