FreeRtos任务管理

目录

一.什么是多任务系统

二.任务状态

三.常用函数详解

四.任务管理实验


一.什么是多任务系统

        不同于我们之前学习的51,32等单片机裸机(未使用操作系统),我们一般编写代码主要在main函数中,将封装好的函数放置main函数的一个主循环中,代码按照先后顺序来执行,中断服务函数触发可打断主函数的执行,来执行中断服务函数,这个就是单任务系统。FreeRtos是一个抢占式的实时多任务系统,其任务调度器也是抢占式的,它通过给任务分配优先级,优先级别高的先执行,高优先级的任务执行完而后将CPU的使用权交给低优先级的任务。

二.任务状态

1.就绪态:该任务处于就绪列表当中,已经具备执行的能力,等待任务调度器进行调度,新创建的任务初始化为就绪态。

2.运行态:任务处于运行状态中,此时该任务正在占用CPU。

3.阻塞态:如果任务当前正在等待某个时序或外部中断,我们就说这个任 务处于阻塞状态,该任务不在就绪列表中。包含任务被挂起、任务被延时、任务 正在等待信号量、读写队列或者等待读写事件等。

4.挂起态:当任务被挂起时,对于任务调度器来说是不可见的,该任务不会被任务调度器所调度。让任务处于挂起态仅能通过调用 vTaskSuspend()函数,而将处于挂起态任务的恢复的途径是调用 vTaskResume() 或 vTaskResumeFromISR()函 数(带ISR指仅可在中断中使用),调用这两个函数便可将处于挂起态的任务重新恢复成正常任务,能够重新别任务调度器所识别,进行正常的任务调度。

三.常用函数详解

1.任务挂起函数

void vTaskSuspend(TaskHandle_t xTaskToSuspend)

xTaskToSuspend:该参数为要挂起的任务句柄,如果使用函数xTaskCreate()创建任务的话那么函数的参数pxCreatedTask 就是此任务的任务句柄,如果使用函数xTaskCreateStatic()创建任务的话那么函数的返回值就是此任务的任务句柄。。通过传入指定的任务句柄,则挂起的任务不会获得CPU的使用权,除非将其解除挂起状态不然无法被任务调度器所调度。

void vTaskSuspendAll(void)

挂起所有的任务,所有任务无法得到cpu的使用权,无法正常执行。

2.任务恢复函数

void vTaskResume(TaskHandle_t xTaskToResume)

TaskHandle_t xTaskToResume:参数为需要恢复的任务句柄,将一个任务从挂起态恢复到就绪态。只有通过函数vTaskSuspend()设置为挂起态的任务才可以使用vTaskRexume()恢复!

void xTaskResumeFromISR(TaskHandle_t xTaskToResume与上述函数类似运用于中断服务函数当中

3.任务删除函数

void vTaskDelect(TaskHandle_t xTaskToDelect)

TaskHandle_t xTaskToDelect:参数为需要删除的任务的任务句柄删除的任务将从所有就绪,阻塞, 挂起和事件列表中删除。

4..任务延时函数

void xTaskDelay(const TickType_t xTickToDelay)

通过该函数能够让每个处于死循环的任务进入阻塞态,这样高优先级的任务在使用CPU执行完任务后,通过任务延时函数进入阻塞态,让出CPU的使用权,给低优先级别的任务使用CPU执行任务。

void vTaskDelayUntil()

这个绝对延时常用于较精确的周期运行任务,比如我有一个任务希望它以固定频率定期执行,而不受外部的影响,任务从上一次运行开始到下一次运行开始的时间间隔是绝对的,而不是相对的。

四.任务管理实验
#include "FreeRTOS.h"
#include "task.h"
#include "bsp_led.h"
#include "bsp_usart.h"

/**************************** 任务句柄 ********************************/
/* 任务句柄是一个指针,用于指向一个任务,当任务创建好之后,它就具有了一个任务句柄
 * 以后我们想要操作这个任务都需要这个任务句柄,如果是自身操作自己,那么
 * 这个句柄就是NULL
 * 
 */

 /* 创建任务任务句柄 */
 TaskHandle_t AppTaskCreate_Handle = NULL;
/* LED任务句柄*/
 TaskHandle_t LED_Task_Handle = NULL;
/* KEY任务句柄 */
 TaskHandle_t KEY_Task_Handle = NULL;

/*
*************************************************************************
*                             函数声明
*************************************************************************
*/
void AppTaskCreate(void);/*用于任务创建 */
void LED_Task(void* Parameter);/* LED_Task任务 */
void KEY_Task(void* parameter); /* 按键任务 */
void BSP_Init(void);/* 用于初始化板载相关资源 */
/*****************************************************************
  * @brief  主函数
  * @param  无
  * @retval 无
  * @note   第一步:开发板硬件初始化 
            第二步:创建APP应用任务
            第三步:启动FreeRTOS,开始多任务调度
  ****************************************************************/
int main(void)
{	
  BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */

  /* 开发板硬件初始化 */
  BSP_Init();

   /* 创建AppTaskCreate任务 */
  xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate,  /* 任务入口函数 */
                        (const char*    )"AppTaskCreate",/* 任务名字 */
                        (uint16_t       )512,  /* 任务栈大小 */
                        (void*          )NULL,/* 任务入口函数参数 */
                        (UBaseType_t    )1, /* 任务的优先级 */
                        (TaskHandle_t*  )&AppTaskCreate_Handle);/* 任务控制块指针 */ 
  /* 启动任务调度 */           
  if(pdPASS == xReturn)
    vTaskStartScheduler();   /* 启动任务,开启调度 */
  else
    return -1;  
  
  while(1);   /* 正常不会执行到这里 */    
}
void AppTaskCreate(void)
{
	taskENTER_CRITICAL();           //进入临界区
	      /* 创建LED_Task任务 */
  xTaskCreate((TaskFunction_t )LED_Task, /* 任务入口函数 */
              (const char*    )"LED_Task",/* 任务名字 */
              (uint16_t       )128,   /* 任务栈大小 */
              (void*          )NULL,	/* 任务入口函数参数 */
              (UBaseType_t    )2,	    /* 任务的优先级 */
              (TaskHandle_t*  )&LED_Task_Handle);/* 任务控制块指针 */
				  /* 创建KEY_Task任务 */
  xTaskCreate((TaskFunction_t )KEY_Task,  /* 任务入口函数 */
			  (const char*    )"KEY_Task",/* 任务名字 */
			  (uint16_t       )256,  /* 任务栈大小 */
			  (void*          )NULL,/* 任务入口函数参数 */
			  (UBaseType_t    )6, /* 任务的优先级 */
			  (TaskHandle_t*  )&KEY_Task_Handle);/* 任务控制块指针 */
  vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务
  
  taskEXIT_CRITICAL();            //退出临界区
}
 void LED_Task(void* parameter)
{

    /*初始化USART 配置模式为 115200 8-N-1,中断接收*/
    USART_Config();

    /* 发送一个字符串 */
		printf("FreeRTOS中断管理实验\r\n");

    while (1)
    {
        LED1_ON;
        vTaskDelay(500);   /* 延时500个tick */      
				LED1_OFF;     
        vTaskDelay(500);   /* 延时500个tick */	


    }
}
 void KEY_Task(void* parameter)  //任务挂起与恢复按键
{
	
	uint8_t key=0;
	
	while(1)
	{
		key=Key_GetNum();
		if(key== 1)
		{
			printf("%d\r\n",key);
			//OLED_ShowString(2,1,"KEY:");
			//OLED_ShowNum(2,5,key,1);
			vTaskSuspend(LED_Task_Handle);/* 挂起LED任务 */
			
			
		}
		else if(key== 2)
		{
			vTaskResume(LED_Task_Handle);/* 恢复LED任务!*/
			//OLED_ShowString(2,1,"KEY:");
			//OLED_ShowNum(2,5,key,1);   //OLED显示key的值
			printf("%d\r\n",key);   //将key的值打印至串口
		}
		
		vTaskDelay(20);
	
	}
}
void BSP_Init(void)
{
	/*
	 * STM32中断优先级分组为4,即4bit都用来表示抢占优先级,范围为:0~15
	 * 优先级分组只需要分组一次即可,以后如果有其他的任务需要用到中断,
	 * 都统一用这个优先级分组,千万不要再分组,切忌。
	 */
	SysTick_Init(72);//延时时钟初始化
	
	NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
	

	
	/* LED 初始化 */
	LED_GPIO_Config();
	/*串口初始化*/
	 USART_Config();		
	/*按键初始化*/
	Key_GPIO_Config();
}	

实验现象为按下按键1则LED_Task任务被挂起,LED停止闪烁,串口接收内容key的值为1.按下按键2LED_Task恢复运行,LED继续闪烁,串口接收内容key的值为2。

参考博客:

https://blog.csdn.net/tichimi3375/article/details/80671840

https://blog.csdn.net/qq_61672347/article/details/125554394?spm=1001.2014.3001.5502

  • 14
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值