FreeRTOS任务函数 - 2优先级控制

文章详细描述了如何在FreeRTOS中使用uxTaskPriorityGet和vTaskPrioritySet函数来管理和调整任务优先级,通过LED和按键操作演示了优先级变化对任务执行的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在创建任务时,可以指定其优先级。在任务运行过程中,可以通过 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使用权,低优先级的任务就不会运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值