操作系统---FreeRTOS(学习笔记四)

FreeRTOS任务创建与删除实验

动态创建

实验:

1.创建start任务;

2.再start任务里面创建LED0、LED1、KEY三个任务;

3.LED0函数功能为每500ms翻转一次;

   LED1函数功能为每500ms翻转一次;

   KEY函数功能为按下删除LED0任务;

注:我的板子按键为PB12,按下为低电平;LED灯是PB14和PB15,低电平点亮。

流程:

1.将configSUPPORT_STSTIC_ALLOCATION设置为1(无需设置,默认就是1);

2.创建开始任务;

3.编写任务函数;

代码实现:

main.c

#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "sys.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>


//任务优先级
#define			START_TASK_PRIO	        1
//任务堆栈大小
#define			START_TASK_STACK_SIZE	128
//任务句柄
TaskHandle_t	start_task_handler;
//开始任务
void start_task(void *pvParameters);

//任务优先级
#define			LED0_TASK_PRIO	        2
//任务堆栈大小
#define			LED0_TASK_STACK_SIZE	128
//任务句柄
TaskHandle_t	led0_task_handler;
//LED0任务
void led0_task(void *pvParameters);

//任务优先级
#define			LED1_TASK_PRIO	        3
//任务堆栈大小
#define			LED1_TASK_STACK_SIZE	128
//任务句柄
TaskHandle_t	led1_task_handler;
//LED1任务
void led1_task(void *pvParameters);


//KEY任务
void key_task(void *pvParameters);
//任务优先级
#define			KEY_TASK_PRIO	        4
//任务堆栈大小
#define			KEY_TASK_STACK_SIZE	    128
//任务句柄
TaskHandle_t	key_task_handler;


 int main(void)
 {	

	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组 4 
	 GPIO_INIT();
	 KEY_INIT();
	 uart_init(9600);
	 
//创建开始任务
	xTaskCreate( (TaskFunction_t         )  start_task,				//任务函数指针
				 (char *                 )  "start_task", 			//任务函数名称
				 (configSTACK_DEPTH_TYPE )  START_TASK_STACK_SIZE,	//任务堆栈大小
				 (void *                 )  NULL,					//传递给任务函数的参数(一般为空)
				 (UBaseType_t            )  START_TASK_PRIO,		//任务优先级
				 (TaskHandle_t *         )  &start_task_handler );	//任务句柄

//开启任务调度				 
    vTaskStartScheduler();    

		 	  
}
 
 开始任务函数
void start_task(void *pvParameters)
{
	 taskENTER_CRITICAL();           //进入临界区
	//创建LED0任务
	xTaskCreate( (TaskFunction_t         )  led0_task,
				 (char *                 )  "led0_task", 
				 (configSTACK_DEPTH_TYPE )  LED0_TASK_STACK_SIZE,
				 (void *                 )  NULL,
				 (UBaseType_t            )  LED0_TASK_PRIO,
				 (TaskHandle_t *         )  &led0_task_handler );
	
	//创建LED1任务
	xTaskCreate( (TaskFunction_t         )  led1_task,
				 (char *                 )  "led1_task", 
				 (configSTACK_DEPTH_TYPE )  LED1_TASK_STACK_SIZE,
				 (void *                 )  NULL,
				 (UBaseType_t            )  LED1_TASK_PRIO,
				 (TaskHandle_t *         )  &led1_task_handler );
				 
//	//创建KEY任务
	xTaskCreate( (TaskFunction_t         )  key_task,
				 (char *                 )  "key_task", 
				 (configSTACK_DEPTH_TYPE )  KEY_TASK_STACK_SIZE,
				 (void *                 )  NULL,
				 (UBaseType_t            )  KEY_TASK_PRIO,
				 (TaskHandle_t *         )  &key_task_handler );

				 				 
	//删除自己
	vTaskDelete(NULL);
	taskEXIT_CRITICAL();            //退出临界区
	
}

//LED0 任务函数
void led0_task(void *pvParameters)
{
	while(1)
	{
		printf("任务1在运行\n");
 		LED0_TOGGLE();
		vTaskDelay(500);
	}

}

//LED1 任务函数
void led1_task(void *pvParameters)
{
	while(1)
	{
		printf("任务2在运行\n");
 		LED1_TOGGLE();
		vTaskDelay(500);		
	}
}

//KEY 任务函数
void key_task(void *pvParameters)
{
	
	u8 key;
	
	while(1)
	{
		key=KEY_SCAN();
		printf("任务3在运行\n");
			if(key==1)
			{
				if(led0_task_handler!=NULL)
				{
					printf("删除LED0函数\n");
					vTaskDelete(led0_task_handler);
					led0_task_handler = NULL;
				}
			}
			vTaskDelay(20);
		}

}


led.c

#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>
#include "delay.h"
//技术支持:   

//初始化PA6和PA7为输出口.并使能GPIOA的时钟		    
//LED IO初始化
void GPIO_INIT()
 {
	 
		GPIO_InitTypeDef  GPIO_InitStructure;
 	
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PB,PE端口时钟
			
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14|GPIO_Pin_15;				 //LED0-->PB.5 端口配置
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
	 
		GPIO_Init(GPIOB, &GPIO_InitStructure);	
 }
 
void KEY_INIT(void)
{
	
	GPIO_InitTypeDef  GPIO_InitStructure;
 	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PB,PE端口时钟
			
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;          //按键接到了PA12引脚
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;      //设置为上拉输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz

	GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB.5

}
 
void LED0_TOGGLE(void)
 {
	u8 led_state = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14);

	if(led_state == 0)
	{
		LED0_OFF;
	}
	else
	{
		LED0_ON;
	}
 
 }
 
void LED1_TOGGLE(void)
 {
	u8 led_state = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_15);

	if(led_state == 0)
	{
		LED1_OFF;
	}
	else
	{
		LED1_ON;
	}
 }
 
 
u8 KEY_SCAN(void)
{
	// 按键WK UP
	if (KEY_UP == 0)
	{
		vTaskDelay(10);   // 延时10ms消抖
		if (KEY_UP == 0)
		{
			while (KEY_UP);   // 松手检测
			
			return 1;
		}else
		{
			return 0;
		}
	}
	return 0;

}

led.h

#ifndef __LED_H
#define __LED_H	 
#include "sys.h"
//技术支持:

#define	 	LED0_OFF 		GPIO_SetBits(GPIOB,GPIO_Pin_14);	
#define		LED0_ON 		GPIO_ResetBits(GPIOB,GPIO_Pin_14);

#define	 	LED1_OFF 		GPIO_SetBits(GPIOB,GPIO_Pin_15);	
#define		LED1_ON 		GPIO_ResetBits(GPIOB,GPIO_Pin_15);

#define 	KEY_UP 			GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12)

void GPIO_INIT(void);//初始化
void LED0_TOGGLE(void);
void LED1_TOGGLE(void);
u8 KEY_SCAN(void);
		 				    
#endif

临界区作用:关闭中断(任务切换就是在中断中进行的)

taskENTER_CRITICAL();           //进入临界区

taskEXIT_CRITICAL();            //退出临界区

不添加临界区,使用串口打印你会发现:

任务2的优先级更高,但是先打印的确实任务1;这是因为在创建任务1时,创建完成直接加入了就绪列表,立马开始执行,执行到延时函数时才会创建任务2开始执行。

添加临界区之后:

会把所有任务创建完成之后,才根据优先级大小开始执行。

静态创建 

代码实现:

main.c

#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "sys.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"


//开始任务
void start_task(void *pvParameters);
//任务优先级
#define			START_TASK_PRIO	        1
//任务堆栈大小
#define			START_TASK_STACK_SIZE	50
//任务句柄
TaskHandle_t	start_task_handler;
//任务堆栈
StackType_t		start_task_stack[START_TASK_STACK_SIZE];
//任务控制块
StaticTask_t	start_task_tcb;


//LED0任务
void led0_task(void *pvParameters);
//任务优先级
#define			LED0_TASK_PRIO	        2
//任务堆栈大小
#define			LED0_TASK_STACK_SIZE	50
//任务句柄
TaskHandle_t	led0_task_handler;
//任务堆栈
StackType_t		led0_task_stack[LED0_TASK_STACK_SIZE];
//任务控制块
StaticTask_t	led0_task_tcb;


//LED1任务
void led1_task(void *pvParameters);
//任务优先级
#define			LED1_TASK_PRIO	        3
//任务堆栈大小
#define			LED1_TASK_STACK_SIZE	50
//任务句柄
TaskHandle_t	led1_task_handler;
//任务堆栈
StackType_t		led1_task_stack[LED1_TASK_STACK_SIZE];
//任务控制块
StaticTask_t	led1_task_tcb;


//KEY任务
void key_task(void *pvParameters);
//任务优先级
#define			KEY_TASK_PRIO	         4
//任务堆栈大小
#define			KEY_TASK_STACK_SIZE	     50
//任务句柄
TaskHandle_t	key_task_handler;
//任务堆栈
StackType_t		key_task_stack[KEY_TASK_STACK_SIZE];
//任务控制块
StaticTask_t	key_task_tcb;


StaticTask_t idle_task_tcb;
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];

//空闲任务内存分配 
void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
									StackType_t ** ppxIdleTaskStackBuffer,
									uint32_t * pulIdleTaskStackSize )
{
	* ppxIdleTaskTCBBuffer   = &idle_task_tcb;
	* ppxIdleTaskStackBuffer = idle_task_stack;
	* pulIdleTaskStackSize     = configMINIMAL_STACK_SIZE;

}

 int main(void)
 {	

	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组 4 
	 GPIO_INIT();
	 KEY_INIT();
	 uart_init(9600);

	 start_task_handler	= xTaskCreateStatic(  (TaskFunction_t) start_task,
								(char *        ) "start_task", 
								(uint32_t      ) START_TASK_STACK_SIZE,
								(void *        ) NULL,
								(UBaseType_t   ) START_TASK_PRIO,
								(StackType_t * ) start_task_stack,
								(StaticTask_t *) &start_task_tcb );
	
//开启任务调度				 
    vTaskStartScheduler();          
}		 	  
//开始 任务函数
void start_task(void *pvParameters)
{
	printf("666\n");
	//进入临界区
	taskENTER_CRITICAL();
	//LED0创建任务
	led0_task_handler =	xTaskCreateStatic(  (TaskFunction_t) led0_task,
							 (char *        ) "led0_task", 
							 (uint32_t      ) LED0_TASK_STACK_SIZE,
							 (void *        ) NULL,
							 (UBaseType_t   ) LED0_TASK_PRIO,
							 (StackType_t * ) led0_task_stack,
							 (StaticTask_t *) &led0_task_tcb );
			//LED1创建任务				 
	led1_task_handler =	xTaskCreateStatic(  (TaskFunction_t) led1_task,
							 (char *        ) "led1_task", 
							 (uint32_t      ) LED1_TASK_STACK_SIZE,
							 (void *        ) NULL,
							 (UBaseType_t   ) LED1_TASK_PRIO,
							 (StackType_t * ) led1_task_stack,
							 (StaticTask_t *) &led1_task_tcb );
			//按键任务创建				 
    key_task_handler = xTaskCreateStatic(  (TaskFunction_t) key_task,
							 (char *        ) "key_task", 
							 (uint32_t      ) KEY_TASK_STACK_SIZE,
							 (void *        ) NULL,
							 (UBaseType_t   ) KEY_TASK_PRIO,
							 (StackType_t * ) key_task_stack,
							 (StaticTask_t *) &key_task_tcb );

	//删除自己
	vTaskDelete(NULL);
	//退出临界区
	taskEXIT_CRITICAL();
}


//LED0 任务函数
void led0_task(void *pvParameters)
{
	while(1)
	{
		printf("任务1在运行\n");
 		LED0_TOGGLE();
		vTaskDelay(500);		
	}
}

//LED1 任务函数
void led1_task(void *pvParameters)
{
	while(1)
	{
		printf("任务2在运行\n");
 		LED1_TOGGLE();
		vTaskDelay(500);		
	}
}

//KEY 任务函数
void key_task(void *pvParameters)
{
	u8 key;
	while(1)
	{
		key=KEY_SCAN();
		printf("任务3在运行\n");
		if(key==1)
		{
			if(led0_task_handler!=NULL)
			{
				printf("删除LED0函数\n");
				vTaskDelete(led0_task_handler);
				led0_task_handler = NULL;
			}
		}
		vTaskDelay(20);
	}

}

led.c和led.h同上。

区别

1.静态创建的时候,要先给空闲任务和定时器任务分配内存,定时器任务不是必需的,上面代码没有配置定时器任务。

2.静态创建相比动态创建需要手动分配任务堆栈和任务控制块,动态创建时FreeRTOS系统从自身管理堆中自动分配的。

3.静态任务需要通过任务句柄接收xTaskCreateStatic()函数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值