任务挂起:暂停某个任务的执行
任务恢复:让暂停的任务继续执行
通过任务挂起和恢复,可以达到让任务停止一段时间后重新运行。
相关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个时钟节拍 }
}
编译即可