任務掛起:暫停某個任務的執行
任務恢復:讓暫停的任務繼續執行
通過任務掛起和恢復,可以達到讓任務停止一段時間后重新運行。
相關API函數:
vTaskSuspend
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
- xTaskToSuspend :要掛起任務的任務句柄,如果使用函數xTaskCreate創建任務的話,xTaskCreate的參數pxCreatedTask就是此任務的任務句柄,如果使用xTaskCreateStatic創建任務,那么函數的返回值就是此任務的任務句柄。
vTaskResume
void vTaskResume( TaskHandle_t xTaskToResume ) ;
- xTaskToResume :要恢復的任務的任務句柄
將一個任務從掛起態恢復到就緒態,只有通過vTaskSuspend設置為掛起態的任務才可以使用vTaskResume恢復
xTaskResumeFromISR
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) ;
此函數是vTaskResume的中斷版本,用于在中斷服務函數中恢復一個任務
返回值:
- pdTRUE:恢復運行的任務的任務優先級等于或者高于正在運行的任務(被中斷打斷的任務)
- pdFALSE:恢復運行的任務的任務優先級低于當前運行的任務(被中斷打斷的任務)
實驗程序設計
- start_task:用來創建其他三個任務
- key_task:按鍵服務函數,檢測按鍵的按下結果,根據不同的按鍵結果執行不同的操作
- task1_task:應用任務1
- task2_task:應用任務2
具體代碼:
start_task:
void start_task(void *pvParameters)
{taskENTER_CRITICAL(); //進入臨界區xTaskCreate(key_task,"key_task",KEY_STK_SIZE,NULL,KEY_TASK_PRIO,&KeyTask_Handler);xTaskCreate(task1_task,"task1_task",TASK1_STK_SIZE,NULL,TASK1_TASK_PRIO,&Task1Task_Handler);xTaskCreate(task2_task,"task2_task",TASK2_STK_SIZE,NULL,TASK2_TASK_PRIO,&Task2Task_Handler);taskEXIT_CRITICAL(); //退出臨界區vTaskDelete(StartTask_Handler); //刪除任務
}
key_task:
void key_task(void *pvParameters)
{u8 key;while(1){key=KEY_Scan(0);switch(key){case WKUP_PRES:vTaskSuspend(Task1Task_Handler); //掛起任務1break;case KEY0_PRES:vTaskResume(Task1Task_Handler); //恢復任務1break;case KEY1_PRES:vTaskSuspend(Task2Task_Handler);break;case KEY2_PRES:vTaskResume(Task2Task_Handler);break; }vTaskDelay(10); //延遲10ms}}
task1_task:
//task1任務函數
void task1_task(void *pvParameters)
{u8 task1_num=0;POINT_COLOR = BLACK;LCD_DrawRectangle(5,110,115,314); //畫一個矩形 LCD_DrawLine(5,130,115,130); //畫線POINT_COLOR = BLUE;LCD_ShowString(6,111,110,16,16,"Task1 Run:000");while(1){task1_num++; //任務執1行次數加1 注意task1_num1加到255的時候會清零!!LED0=!LED0;LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充區域LCD_ShowxNum(86,111,task1_num,3,16,0x80); //顯示任務執行次數vTaskDelay(1000); //延時1s,也就是1000個時鐘節拍 }
}
task2_task
//task2任務函數
void task2_task(void *pvParameters)
{u8 task2_num=0;POINT_COLOR = BLACK;LCD_DrawRectangle(125,110,234,314); //畫一個矩形 LCD_DrawLine(125,130,234,130); //畫線POINT_COLOR = BLUE;LCD_ShowString(126,111,110,16,16,"Task2 Run:000");while(1){task2_num++; //任務2執行次數加1 注意task1_num2加到255的時候會清零!!LED1=!LED1;//printf("任務2已經執行:%d次\r\n",task2_num);LCD_ShowxNum(206,111,task2_num,3,16,0x80); //顯示任務執行次數LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //填充區域vTaskDelay(1000); //延時1s,也就是1000個時鐘節拍 }
}
main.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "sdram.h"
#include "key.h"
#include "exti.h"
#include "FreeRTOS.h"
#include "task.h"//任務優先級
#define START_TASK_PRIO 1
//任務堆棧大小
#define START_STK_SIZE 128
//任務句柄
TaskHandle_t StartTask_Handler;
//任務函數
void start_task(void *pvParameters);//任務優先級
#define KEY_TASK_PRIO 2
//任務堆棧大小
#define KEY_STK_SIZE 128
//任務句柄
TaskHandle_t KeyTask_Handler;
//任務函數
void key_task(void *pvParameters);//任務優先級
#define TASK1_TASK_PRIO 3
//任務堆棧大小
#define TASK1_STK_SIZE 128
//任務句柄
TaskHandle_t Task1Task_Handler;
//任務函數
void task1_task(void *pvParameters);//任務優先級
#define TASK2_TASK_PRIO 4
//任務堆棧大小
#define TASK2_STK_SIZE 128
//任務句柄
TaskHandle_t Task2Task_Handler;
//任務函數
void task2_task(void *pvParameters);//LCD刷屏時使用的顏色
int lcd_discolor[14]={ WHITE, BLACK, BLUE, BRED, GRED, GBLUE, RED, MAGENTA, GREEN, CYAN, YELLOW,BROWN, BRRED, GRAY };int main(void)
{HAL_Init(); //初始化HAL庫 Stm32_Clock_Init(360,25,2,8); //設置時鐘,180Mhzdelay_init(180); //初始化延時函數uart_init(115200); //初始化串口LED_Init(); //初始化LED KEY_Init(); //初始化按鍵SDRAM_Init(); //初始化SDRAMLCD_Init(); //初始化LCDPOINT_COLOR = RED;LCD_ShowString(30,10,200,16,16,"Apollo STM32F4/F7"); LCD_ShowString(30,30,200,16,16,"FreeRTOS Examp 6-3");LCD_ShowString(30,50,200,16,16,"Task Susp and Resum");//LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,90,200,16,16,"2021/11/21");xTaskCreate(start_task,"start_task",START_STK_SIZE,NULL,START_TASK_PRIO,&StartTask_Handler);vTaskStartScheduler(); //開啟糞污調度}void start_task(void *pvParameters)
{taskENTER_CRITICAL(); //進入臨界區xTaskCreate(key_task,"key_task",KEY_STK_SIZE,NULL,KEY_TASK_PRIO,&KeyTask_Handler);xTaskCreate(task1_task,"task1_task",TASK1_STK_SIZE,NULL,TASK1_TASK_PRIO,&Task1Task_Handler);xTaskCreate(task2_task,"task2_task",TASK2_STK_SIZE,NULL,TASK2_TASK_PRIO,&Task2Task_Handler);taskEXIT_CRITICAL(); //退出臨界區vTaskDelete(StartTask_Handler); //刪除任務
}void key_task(void *pvParameters)
{u8 key;while(1){key=KEY_Scan(0);switch(key){case WKUP_PRES:vTaskSuspend(Task1Task_Handler); //掛起任務1break;case KEY0_PRES:vTaskResume(Task1Task_Handler); //恢復任務1break;case KEY1_PRES:vTaskSuspend(Task2Task_Handler);break;case KEY2_PRES:vTaskResume(Task2Task_Handler);break; }vTaskDelay(10); //延遲10ms}}//task1任務函數
void task1_task(void *pvParameters)
{u8 task1_num=0;POINT_COLOR = BLACK;LCD_DrawRectangle(5,110,115,314); //畫一個矩形 LCD_DrawLine(5,130,115,130); //畫線POINT_COLOR = BLUE;LCD_ShowString(6,111,110,16,16,"Task1 Run:000");while(1){task1_num++; //任務執1行次數加1 注意task1_num1加到255的時候會清零!!LED0=!LED0;LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充區域LCD_ShowxNum(86,111,task1_num,3,16,0x80); //顯示任務執行次數vTaskDelay(1000); //延時1s,也就是1000個時鐘節拍 }
}//task2任務函數
void task2_task(void *pvParameters)
{u8 task2_num=0;POINT_COLOR = BLACK;LCD_DrawRectangle(125,110,234,314); //畫一個矩形 LCD_DrawLine(125,130,234,130); //畫線POINT_COLOR = BLUE;LCD_ShowString(126,111,110,16,16,"Task2 Run:000");while(1){task2_num++; //任務2執行次數加1 注意task1_num2加到255的時候會清零!!LED1=!LED1;//printf("任務2已經執行:%d次\r\n",task2_num);LCD_ShowxNum(206,111,task2_num,3,16,0x80); //顯示任務執行次數LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //填充區域vTaskDelay(1000); //延時1s,也就是1000個時鐘節拍 }
}
編譯即可