一、任务挂起和恢复API函数
1.1、函数 vTaskSuspend()
此函数用于将某个任务设置为挂起态,进入挂起态的任务永远都不会进入运行态。退出挂起态的唯一方法就是调用任务恢复函数 vTaskResume()或 xTaskResumeFromISR(),函数原型如下:
参数:
xTaskToSuspend:要挂起的任务的任务句柄,创建任务的时候会为每个任务分配一个任务句柄。如果使用函数 xTaskCreate()创建任务的话那么函数的参数 pxCreatedTask 就是此任务的任务句柄,如果使用函数 xTaskCreateStatic() 创建任务的话那么函数的返回值就是此任务的任务句柄。也可以通过函 数 xTaskGetHandle()来根据任务名字来获取某个任务的任务句柄。 注意!如果参数为 NULL 的话表示挂起任务自己。
返回值: 无
1.2、函数 vTaskResume()
将一个任务从挂起态恢复到就绪态,只有通过函数 vTaskSuspend()设置为挂起态的任务才可以使用 vTaskRexume()恢复!函数原型如下:
参数:
xTaskToResume: 要恢复的任务的任务句柄。
返回值: 无
二、编写代码
2.1、实验任务
本实验设计4个任务:start_task、task1_task、task2_task、key_task,这四个任务的功能分别如下:
start_task:用于创建其他3个任务。
key_task:按键服务任务,检测按键按下的结果,根据不同的按键结果执行不同的操作
task1_task:应用任务1
task2_task:应用任务2
实现需要两个按键,KEY0、KEY1,这两个按键的功能分别如下:
KEY0:此按键为输入按键,用于挂起任务1
KEY1:此按键为输入按键,用于恢复任务1
2.2、开始编写
首先先编写key.c的
编写完key.c的之后,我们接着编写key.h的
最后编写main.c的
#include “led.h”
#include “delay.h”
#include “sys.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 TASK1_TASK_PRIO 3 //任务优先级
#define TASK1_STK_SIZE 128 //任务堆栈大小
TaskHandle_t Task1Task_Handler; //任务句柄
void task1_task(void *pvParameters); //任务函数
#define TASK2_TASK_PRIO 2 //任务优先级
#define TASK2_STK_SIZE 128 //任务堆栈大小
TaskHandle_t Task2Task_Handler; //任务句柄
void task2_task(void *pvParameters); //任务函数
#define KEY_TASK_PRIO 4 //任务优先级
#define KEY_STK_SIZE 128 //任务堆栈大小
TaskHandle_t KeyTask_Handler; //任务句柄
void key_task(void *pvParameters); //任务函数
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级
delay_init(); //延时初始化
uart_init(115200); //串口初始化
LED_Init(); //初始化LED
KEY_Init(); //³õʼ»¯KEY
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(); //开启任务调度
}
//start_task任务函数
void start_task(void *pvParameters)
{
while(1)
{
taskENTER_CRITICAL(); //进入临界区
xTaskCreate( (TaskFunction_t) task1_task, //任务函数
(const char * ) “task1_task”, //任务名称
(uint16_t ) TASK1_STK_SIZE, //任务堆栈大小
(void * ) NULL //传递给任务函数的参数
(UBaseType_t ) TASK1_TASK_PRIO//任务优先级
(TaskHandle_t *) &Task1Task_Handler); //任务句柄
xTaskCreate( (TaskFunction_t) task2_task, //任务函数
(const char * ) "task2_task", //任务名称
(uint16_t ) TASK2_STK_SIZE//任务堆栈大小
(void * ) NULL, //传递给任务函数的参数
(UBaseType_t ) TASK2_TASK_PRIO, //任务优先级
(TaskHandle_t *) &Task2Task_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); //删除start_task()任务
taskEXIT_CRITICAL(); //退出临界区
}
}
//task1_task任务函数
void task1_task(void *pvParameters)
{
int num=0;
while(1)
{
num++;
LED0=~LED0;
printf("\r\n正在运行task1_task:%d\r\n",num);
vTaskDelay(500);
}
}
//task2_task任务函数
void task2_task(void *pvParameters)
{
int num=0;
while(1)
{
num++;
LED1=1;
vTaskDelay(500);
LED1=0;
vTaskDelay(800);
printf("\r\n正在运行tatk2_task:%d\r\n",num);
}
}
//key_task任务函数
void key_task(void *pvParameters)
{
u8 key=0;
while(1)
{
key=KEY_Scan();
switch(key)
{
case Presskey0:
vTaskSuspend(Task1Task_Handler);
printf("\r\n挂起任务1\r\n");
break;
case Presskey1:
vTaskResume(Task1Task_Handler);
printf("\r\n恢复任务1\r\n");
break;
}
vTaskDelay(10);
}
}
一开始任务 1 和任务 2 都正常运行,当摁下按键挂起任务1以后任务1就会停止运行,再次摁下按键即可重新恢复任务1的运行。重点是,保存任务运行次数的变量都没有发生数据丢失,如果用任务删除和重建的方法这些数据必然会丢失掉的
QQ群:
131322621
欢迎大家进群交流!