當前位置:網站首頁>【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
邊欄推薦
猜你喜歡
隨機推薦
- VMware虛擬機 之 NAT模式詳解
- 【Devops】kubernetes網絡
- 新式茶飲“拿捏”年輕人,“八馬茶業”們的出路在哪?
- 機器學習之金融風控
- 1.67版本vscode括號著色(Bracket Pair Colorizer)取消
- MySQL日期查詢使用的方法函數
- HugeGraph客戶端APP開發(一)
- [.Net]使用Soa庫+Abp搭建微服務項目框架(五):服務發現和健康監測
- 添加虛擬內存,不添加硬盤的方式
- Redis源碼學習(25),雙端鏈錶學習,adlist.h
- 虛幻5新特性之EnhancedInput
- 緩存命中錶示什麼?
- sencha touch 在線實戰培訓 第一期 第四節
- “我們從 Google 離職了”
- yolov5訓練測試與源碼解讀
- 原生JS 實現輪播圖效果
- 邏輯回歸 解决報錯:ValueError: Solver lbfgs supports only ‘l2‘ or ‘none‘ penalties, got l1 penalty.
- Oracle OCI 計算、存儲、網絡工具旨在降低雲複雜性
- Go項目實戰之日志必備篇[開源十年項目第11次更新]
- Shell脚本變量和運算符
- 聊聊找工作
- 是能力更是文化,談談IT系統的安全發布
- tensorflow學習筆記(五)
- vitest支持cjs的workaround(TypeScript產物commonjs場景)
- 並發編程系列之Lock鎖可重入性與公平性
- 淺談 Fiori Fundamentals 和 SAP UI5 Web Components 的關系
- RAM/FIFO學習回顧
- 最新版2022年任我行管家婆工貿版ERP M7 V22.0進銷存財務生產管理軟件網絡版——雲上的集團化制造管理系統
- 【機器學習05】LASSO回歸與ElasticNet(彈性網)
- Idea快捷鍵
- 關於創建模態窗口和非模態窗口的研究
- An End-to-End Steel Surface Defect Detection Approach via Fusing Multiple Hierarchical Features-閱讀筆記
- 【性能測試】第五篇 | Jmeter環境安裝
- Matplotlib使用指南,100個案例從入門到進階!(附源代碼)
- Dots + interval stats and geoms
- SIGIR2022 | 基於用戶價格偏好及興趣偏好的會話推薦
- Cloudreve自建雲盤實站:容量和速度自己來决定
- 利用騰訊雲函數搭建免費代理池
- Redis的安裝及基本數據類型
- js輪播圖效果,透明度漸變實現