FreeRTOS任务的创建与调度

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.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 LED1_TASK_PRIO		2
//任务堆栈大小	
#define LED1_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);

//任务优先级
#define LED2_TASK_PRIO		3
//任务堆栈大小	
#define LED2_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED2Task_Handler;
//任务函数
void led2_task(void *pvParameters);

//任务优先级
#define KEY_TASK_PRIO		4
//任务堆栈大小	
#define KEY_STK_SIZE 		50  
//任务句柄
TaskHandle_t KEYTask_Handler;
//任务函数
void key_task(void *pvParameters);


int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
LED_Init();
KEY_Init();
USART1_Init(115200);

//创建开始任务
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();          //开启任务调度
}


void start_task(void *pvParameters)
{
	 taskENTER_CRITICAL();           //进入临界区
  
//创建LED1任务
 xTaskCreate((TaskFunction_t )led1_task,     
            (const char*    )"led1_task",   
            (uint16_t       )LED1_STK_SIZE, 
            (void*          )NULL,
            (UBaseType_t    )LED1_TASK_PRIO,
            (TaskHandle_t*  )&LED1Task_Handler); 
			
//创建LED2任务
xTaskCreate((TaskFunction_t )led2_task,     
            (const char*    )"led2_task",   
            (uint16_t       )LED2_STK_SIZE, 
            (void*          )NULL,
            (UBaseType_t    )LED2_TASK_PRIO,
            (TaskHandle_t*  )&LED2Task_Handler);

//创建KEY任务
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); //删除开始任务
taskEXIT_CRITICAL();            //退出临界区
} 
void led1_task(void *pvParameters)
{
while(1)
{
    LED1=0;
    vTaskDelay(200);
    LED1=1;
    vTaskDelay(800);
}
}


void led2_task(void *pvParameters)
{
  while(1)
{
    LED2=0;
    vTaskDelay(800);
    LED2=1;
    vTaskDelay(200);
 }
}


void key_task(void *pvParameters)
{
	u8 key=0;

while(1)
{
	key=KEY_Scan(0);
	if(key==KEY_UP_PRESS)
	{
		printf("挂起LED任务!\n");
		vTaskSuspend(LED2Task_Handler);/* 挂起LED任务 */
		printf("挂起LED任务成功!\n");
	}
	else if(key==KEY1_PRESS)
	{
		printf("恢复LED任务!\n");
		vTaskResume(LED2Task_Handler);/* 恢复LED任务!*/
		printf("恢复LED任务成功!\n");
	}
	vTaskDelay(20);
    }
}

两个注意的点:一个是任务的切换是在一个中断中完成的,如果在开始任务中不加临界段保护的话,由于开始任务的优先级最低,当开始任务创建完Task1以后,由于此时开启了任务调度,Task1会抢占执行,此时开始任务会等待Task1执行完或者进入阻塞态,再来创建Task2,同理Task2被创建以后也会抢占开始任务执行,等Task2执行完或者进入阻塞态,再来创建Task3.结果就是优先级高的被后执行,临界段的保护导致中断不能打开,使得任务切换在开始任务没结束之前不起作用,避免了优先级的反转。
另外是在中断中挂起或者恢复任务时,中断的优先级不能高于设定的最高值,同时为了方便使用中断应该全配置为抢占式优先级,而不分配响应式优先级。
补充一点,中断的优先级值越小越高,任务的优先级值越高越高,注意这是不一样的!最低优先级的中断可以中断最高优先级的任务。在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值