當前位置:網站首頁>【FreeRtos任務恢複與掛起】

【FreeRtos任務恢複與掛起】

2022-05-15 00:21:43@slow_walker

FreeRtos任務恢複與掛起

本篇內容分享的是FreeRtos中的任務恢複與掛起。
有時候我們需要將暫停某個任務的運行,過一段時間以後在重新運行。這個時候是要適應任務删除和重建的方法的話那麼任務中變量保存的值肯定丟了!FreeRtos給我們提供了解决這種問題的方法,那就是任務的恢複與掛起,當莫個任務要停止運行一段時間的話就將這個任務掛起,當要重新運行這個任務的話就恢複這個任務的運行,FreeRtos的任務掛起與恢複API函數如下:

在這裏插入圖片描述

在這裏插入圖片描述

vTaskSuspend()函數

此函數用於將某個任務設置為掛起態,進入掛起態的任務永遠都不會進入運行態。退出掛起態的唯一方法就是調用任務恢複函數 vTaskResume()xTaskResumeFromISR()

/*-----------------------函數原型-------------------*/
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
//參數為任務句柄

要掛起的任務的任務句柄,創建任務的時候會為每個任務分配一個任務句柄。如果使用函數 xTaskCreate()創建任務的話那麼函數的參數pxCreatedTask 就是此任務的任務句柄,如果使用函數 xTaskCreateStatic()創建任務的話那麼函數的返回值就是此任務的任務句柄。也可以通過函數 xTaskGetHandle()來根據任務名字來獲取某個任務的任務句柄。
注意!如果參數為 NULL 的話錶示掛起任務自己。

vTaskResume()

/*--------------------函數原型------------------*/
void vTaskResume( TaskHandle_t xTaskToResume )
//參數為任務句柄

將一個任務從掛起態恢複到就緒態,只有通過函數 vTaskSuspend()設置為掛起態的任務才可以使用 vTaskRexume()恢複。

xTaskResumeFromISR()

/*-------------------函數原型------------------*/
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume) 

此函數是 vTaskResume()的中斷版本,用於在中斷服務函數中恢複一個任務
返回值:
pdTrue:恢複運行的任務的任務優先級等於或者高於正在運行的任務(被中斷打斷的任務),這意味著在退出中斷服務函數以後必須進行一次上下文切換。
pdFALSE: 恢複運行的任務的任務優先級低於當前正在運行的任務(被中斷打斷的
任務),這意味著在退出中斷服務函數的以後不需要進行上下文切換。

實驗需求

通過兩個按鍵來控制LED0的掛起與恢複

key.h

#ifndef _KEY_H_
#define _KEY_H_
#include "stm32f10x.h"
#include "delay.h"

//#define KEY0 GPIO_Pin_5
//#define KEY1 GPIO_Pin_6
//#define KEY2 GPIO_Pin_7
//#define KEY3 GPIO_Pin_8
//#define KEY4 GPIO_Pin_9

#define GPIO_PORT GPIOB
#define GPIO_PIN GPIO_Pin_4|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9
#define KEY0 GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_9) //讀GPIO端口的輸入,輸入等於0返回1
#define KEY1 GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_8) //讀GPIO端口的輸入,輸入等於0返回2
#define KEY2 GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_7) //讀GPIO端口的輸入,輸入等於0返回3
#define KEY3 GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_6) //讀GPIO端口的輸入,輸入等於0返回4
#define KEY4 GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_4) //讀GPIO端口的輸入,輸入等於0返回4


#define KEY_ON 0 //按鍵按下為0
#define KEY_OFF -1 //按鍵沒有按下為-1
#define KEY0_Value 1 //按鍵1的返回值
#define KEY1_Value 2 //按鍵1的返回值
#define KEY2_Value 3 //按鍵2的返回值
#define KEY3_Value 4 //按鍵3的返回值
#define KEY4_Value 5 //按鍵4的返回值
#define Error -2 //錯誤值返回

void KEY_GPIO_INIT(void);
unsigned char KEY_Scan(void);

#endif

key.c





void KEY_GPIO_INIT(void)
{
    
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitStructure.GPIO_Mode  =  GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin   = GPIO_PIN;
	GPIO_InitStructure.GPIO_Speed =  GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);		
}


//獨立鍵盤掃描函數 
unsigned char KEY_Scan(void)
{
     
// KEY_GPIO_INIT();
		//keyvalue = 0;
	if(KEY0==0||KEY1==0||KEY2==0||KEY3==0)
	{
    
		delay_ms(20);//去抖動 
		if(KEY0==0)   //按鍵0按下
		{
    
			while(KEY0 == 0);
			return KEY0_Value;
		}
		else if(KEY1==0)  //按鍵1按下
		{
    		
				while(KEY1 == 0);
			return KEY1_Value;
		}
		else if(KEY2==0)   //按鍵2按下
		{
    		
			//delay_ms(10);
				while(KEY2 == 0);
			return KEY2_Value;
		}
		else if(KEY3==0) //按鍵3按下
		{
    		
			//delay_ms(10);
				while(KEY3 == 0);
			return KEY3_Value;
		}
		else if(KEY4==0)
		{
    
				while(KEY4 == 0);
			return KEY4_Value;
		}
	}
		return 0;// 無按鍵按下
}

主函數

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


//任務優先級
#define START_TASK_PRIO 1
//任務堆棧大小 
#define START_STK_SIZE 128 
//任務句柄
TaskHandle_t StartTask_Handler;
//任務函數
void start_task(void *pvParameters);

//任務優先級
#define LED0_TASK_PRIO 4
//任務堆棧大小 
#define LED0_STK_SIZE 50 
//任務句柄
TaskHandle_t LED0Task_Handler;
//任務函數
void led0_task(void *pvParameters);

//任務優先級
#define LED1_TASK_PRIO 3
//任務堆棧大小 
#define LED1_STK_SIZE 50 
//任務句柄
TaskHandle_t LED1Task_Handler;
//任務函數
void led1_task(void *pvParameters);


//按鍵任務

#define KEY_TASK_PRIO 2
//任務堆棧大小 
#define KEY_STK_SIZE 50 
//任務句柄
TaskHandle_t KEYTask_Handler;
//任務函數
void key_task(void *pvParameters);



int main(void)
{
    
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//設置系統中斷優先級分組4 
	delay_init();	    				//延時函數初始化 
	uart_init(115200);					//初始化串口
	LED_Init();		  					//初始化LED
	KEY_GPIO_INIT();          //按鍵初始化
	 
	//創建開始任務
    xTaskCreate((TaskFunction_t )start_task,            //任務函數
                (const char*    )"start_task",          //任務名稱
                (uint16_t       )START_STK_SIZE,        //任務堆棧大小
                (void*          )NULL,                  //傳遞給任務函數的參數
                (UBaseType_t    )START_TASK_PRIO,       //任務優先級
                (TaskHandle_t*  )&StartTask_Handler);   //任務句柄 
    vTaskStartScheduler();          //開啟任務調度
}

//開始任務任務函數
void start_task(void *pvParameters)
{
    
    taskENTER_CRITICAL();           //進入臨界區
    //創建LED0任務
    xTaskCreate((TaskFunction_t )led0_task,     	
                (const char*    )"led0_task",   	
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED0_TASK_PRIO,	
                (TaskHandle_t*  )&LED0Task_Handler);   
    //創建LED1任務
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);    

		//創建按鍵任務
		xTaskCreate((TaskFunction_t )key_task,     
                (const char*    )"key_task",   
                (uint16_t       )KEY_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )KEY_TASK_PRIO,
                (TaskHandle_t*  )&KEYTask_Handler);    
	
    vTaskDelete(StartTask_Handler); //删除開始任務
    taskEXIT_CRITICAL();            //退出臨界區
}

//LED0任務函數 
void led0_task(void *pvParameters)
{
    
    while(1)
    {
    
        LED0=~LED0;
        vTaskDelay(500);
			  printf("led1 is running\r\n");
    }
}   

//LED1任務函數
void led1_task(void *pvParameters)
{
    
    while(1)
    {
    
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
				printf("led2 is running\r\n");
    }
}



//按鍵任務函數
void key_task(void *pvParameters)
{
    
    while(1)
    {
    
			//功能代碼
			//使用兩個震動傳感器 一個用於掛起 一個用於解掛
			if(GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_9) == 0)
			{
    
				delay_ms(20); //消抖
				while(GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_9) == 0); //等待按鍵抬起
				vTaskDelay(100);
				//掛起
				vTaskSuspend(LED0Task_Handler);
				printf("Task0 is Suspend\r\n");
			}
			
			if(GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_8) == 0)
			{
    
					delay_ms(20); //消抖
				while(GPIO_ReadInputDataBit(GPIO_PORT,GPIO_Pin_8) == 0); //等待按鍵抬起
				vTaskDelay(100);
				//掛起
				vTaskResume(LED0Task_Handler);
				printf("Task0 is Resume\r\n");
			}
        
    }
}

實驗結果

在這裏插入圖片描述

版權聲明
本文為[@slow_walker]所創,轉載請帶上原文鏈接,感謝
https://cht.chowdera.com/2022/135/202205141952071917.html

隨機推薦