在创建任务时,可以指定其优先级。在任务运行过程中,可以通过 uxTaskPriorityGet()函数查询任务优先级,通过vTaskPrioritySet()函数改变任务优先级。
1 获取任务优先级
uxTaskPriorityGet()函数用于获取指定任务的优先级。使用此函数,需要设置宏INCLUDE_uxTaskPriorityGet为1。获取任务优先级函数的原型如下。
UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask )
参数说明如下。
xTask: 要查询任务的任务句柄,为NULL时表示查询调用此函数的任务的优先级。
返回值:获取到的任务优先级数。
2 设置任务优先级
vTaskPrioritySet()函数用于设置指定任务的优先级。使用此函数,需要设置宏INCLUDE_vTaskPrioritySet为1。设置任务优先级函数的原型如下。
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority )
参数说明如下。
xTask:要设置优先级的任务句柄。
uxNewPriority:要设置的新优先级,范围为0~configMAX_PRIORITIES-1。
返回值:无。
3 改变任务优先级示例
本示例通过appStartTask()函数创建两个具有相同优先级的FreeRTOS任务,均运行于优先级3。
为便于观察,将宏configUSE_TIME_SLICING设置为0,禁止时间片调度,并且在任务1和任务2中均不调用任何会使任务进入阻塞态的API函数,这样任务1和任务2中就只有一个任务能得到运行。
任务1的任务函数为Led0Task(),其功能是使LED0闪烁,统计任务运行次数并通过串口发送,当检测到Key1按键被按下时,将任务2的优先级提升到比任务1的优先级高一级,注意不要超出宏configMAX_PRIORITIES设置的最大优先级数。(本任务的configMAX_PRIORITIES为5)
任务2的任务函数为Led1Task(),其功能是使LED1闪烁,统计任务运行次数并通过串口发送,当检测到Key2按键被按下时,将任务2的优先级降低到比任务1的优先级低一级。
3.1 按键处理代码
#include "stm32f10x.h" // Device header
#include "Key.h"
void Key_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStruvture;
GPIO_InitStruvture.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStruvture.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStruvture.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruvture);
}
//返回KeyNum =1 为Key1被按下
//返回KeyNum =2 为Key2被按下
uint8_t Key_getNum(void)
{
static uint8_t KeyNum=0;
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)==0){
Delay(60000); //20ms 消抖
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)==0);
KeyNum=1;
}
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7)==0){
Delay(60000); //20ms 消抖
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7)==0);
KeyNum=2;
}
return KeyNum;
}
3.2 任务函数
#include "stm32f10x.h" // Device header
#include "appTask.h"
#include "LED.h"
#include "Delay.h"
#include "Serial.h"
#include "Key.h"
static TaskHandle_t Led0TaskHandle = NULL;//任务LED0任务句柄
static TaskHandle_t Led1TaskHandle = NULL;//任务LED1任务句柄
/**********************************************************************
函 数 名:Led0Task
形 参:pvParameters 是在创建该任务时传递的参数
返 回 值:无
优 先 级: 3
**********************************************************************/
static void Led0Task(void *pvParameters)
{
uint16_t cnt = 0; //检测灯闪烁次数的局部变量
UBaseType_t uxPriority; //用于保存优先级值
while(1)
{
GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_4))); //LED0闪烁
cnt++;
taskENTER_CRITICAL(); //进入临界段,开中断
printf("任务1:LED0 闪烁,任务已经运行 %3d \r\n",cnt);
taskEXIT_CRITICAL();//退出临界段,关中断
uxPriority = uxTaskPriorityGet(NULL);
if(Key_getNum() == 1)
{
printf("提升任务2的优先级至任务1上 \r\n");
vTaskPrioritySet(Led1TaskHandle,uxPriority+1); //设置任务2的优先级
}
my_delay_ms(1000);
}
}
/**********************************************************************
函 数 名:Led1Task
形 参:pvParameters 是在创建该任务时传递的参数
返 回 值:无
优 先 级: 3
**********************************************************************/
static void Led1Task(void *pvParameters)
{
uint16_t cnt = 0; //检测灯闪烁次数的局部变量
UBaseType_t uxPriority; //用于保存优先级值
while(1)
{
GPIO_WriteBit(GPIOA,GPIO_Pin_5,(BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_5))); //LED1闪烁
cnt++;
taskENTER_CRITICAL(); //进入临界段,开中断
printf("任务2:LED1 闪烁,任务已经运行 %3d \r\n",cnt);
taskEXIT_CRITICAL();//退出临界段,关中断
uxPriority = uxTaskPriorityGet(Led0TaskHandle); //获取任务1的优先级
if(Key_getNum() == 2)
{
printf("降低任务2的优先级至任务1下 \r\n");
vTaskPrioritySet(Led1TaskHandle,uxPriority-1); //设置任务2的优先级
}
my_delay_ms(500); //延时250ms
}
}
/**********************************************************************
函 数 名:appStartTask
功能说明:任务开始函数,用于创建其他函数并且开启调度器
形 参:pvParameters 是在创建该任务时传递的参数
返 回 值:无
**********************************************************************/
void appStartTask(void)
{
taskENTER_CRITICAL(); /*进入临界段,关中断*/
xTaskCreate(Led0Task,"Led0Task",128,NULL,3,&Led0TaskHandle);
xTaskCreate(Led1Task,"Led1Task",128,NULL,3,&Led1TaskHandle);
taskEXIT_CRITICAL(); /*退出临界段,关中断*/
vTaskStartScheduler();/*开启调度器*/
}
3.3 下载测试
编译无误后将程序下载到开发板上,可以看到LED1以每秒2次的频率闪烁。同时,串口调试助手显示任务2在运行,其运行次数不断增加,这是因为任务1和任务2在创建时具有相同的优先级,都为优先级3。由于时间片调度被禁止,所以只有后创建的任务2在运行。
按下Key1按键后,任务2的优先级被设置成比任务1的优先级低一级。此时任务1的优先级比任务2高,任务1获得CPU 使用权。按下 Key2 按键后,把任务2的优先级提高到任务1的优先级之上,任务2运行。在两个任务中都没有调用任何可能引起任务阻塞的API函数,只要高优先级不主动放弃CPU使用权,低优先级的任务就不会运行。