FreeRTOS标准库例程代码

1.设备STM32F103C8T6

2.工程模板

单片机: 部分单片机的程序例程 - Gitee.comicon-default.png?t=N7T8https://gitee.com/lovefoolnotme/singlechip/tree/master/STM32_FREERTOS/1.%E5%B7%A5%E7%A8%8B%E6%A8%A1%E6%9D%BF

3.代码

1-FreeRTOS移植模板

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.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);


/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	LED_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); 
				
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=!LED1;
			  LED2=!LED2;
			  LED3=!LED3;
			  LED4=!LED4;
        vTaskDelay(500);
    }
}

2-FreeRTOS任务挂起实验

#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.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);


/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
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();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=!LED1;
        vTaskDelay(500);
    }
}

//LED1任务函数
void led2_task(void *pvParameters)
{
    while(1)
    {
			  LED2=!LED2;
        vTaskDelay(500);
    }
}

//LED1任务函数
void key_task(void *pvParameters)
{
    while(1)
    {
     if(KEY==1) vTaskSuspend(LED2Task_Handler); 
			else vTaskResume(LED2Task_Handler);
			vTaskDelay(100);
    }
}

3-FreeRTOS消息队列实验

/******************************2023年10月14日*************************************
此为一个消息队列实验,主要使用使用按键、OLED屏幕来观察现象。
主要创建两个任务一个接收,一个发送
发送不等待,但是需要按键触发
接收是一直等待,直到接收到队列里面的消息,使用本次实验中的函数接收数据后会删除队列中的数据
宏定义队列长度和单个消息大小都为4
需定义队列句柄
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.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 SEND_TASK_PRIO		3
//任务堆栈大小	
#define SEND_STK_SIZE 		50  
//任务句柄
TaskHandle_t SendTask_Handler;
//任务函数
void send_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define RECEIVE_TASK_PRIO		4
//任务堆栈大小	
#define RECEIVE_STK_SIZE 		50  
//任务句柄
TaskHandle_t ReceiveTask_Handler;
//任务函数
void receive_task(void *pvParameters);


QueueHandle_t Test_Queue =NULL;    //句柄
#define  QUEUE_LEN    4            // 队列的长度,最大可包含多少个消息 */
#define  QUEUE_SIZE   4            // 队列中每个消息大小(字节) */

/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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();           //进入临界区
    
	  /* 创建Test_Queue */
	  Test_Queue = xQueueCreate((UBaseType_t ) QUEUE_LEN,/* 消息队列的长度 */
                             (UBaseType_t ) QUEUE_SIZE);/* 消息的大小 */
	  
    //创建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); 						
		
		
		//创建接收任务
    xTaskCreate((TaskFunction_t )receive_task,     
                (const char*    )"receive_task",   
                (uint16_t       )RECEIVE_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )RECEIVE_TASK_PRIO,
                (TaskHandle_t*  )&ReceiveTask_Handler);

	//创建发送任务
    xTaskCreate((TaskFunction_t )send_task,     
                (const char*    )"send_task",   
                (uint16_t       )SEND_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )SEND_TASK_PRIO,
                (TaskHandle_t*  )&SendTask_Handler);
								
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=!LED1;
			  LED2=!LED2;
			  LED3=!LED3;
			  LED4=!LED4;
        vTaskDelay(500);
    }
}


void send_task(void *pvParameters)
{   
	
	BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
	static uint32_t send_data1 = 1;
    while(1)
    {
     if(KEY==1) 
		{
		xReturn = xQueueSend( Test_Queue, /* 消息队列的句柄 */
								&send_data1,/* 发送的消息内容 */
								0 );        /* 等待时间 0 */ 
		if(xReturn==pdPASS)
		{
		 OLED_ShowString(3,0,"ok",8,1);                      //按下显示"ok"
		 OLED_ShowNum(3,20,send_data1,2,8,1);
		 OLED_Refresh();
		 send_data1+=1;         //递增
		}
		}
		else {OLED_ShowString(3,0,"no",8,1);OLED_ShowString(3,40,"   ",8,1);OLED_Refresh();} //没按下时显示"no"
		vTaskDelay(100);
    }
}

//接收任务函数
void receive_task(void *pvParameters)
{
  BaseType_t xReturn = pdTRUE;/* 定义一个创建信息返回值,默认为pdTRUE */
	uint32_t r_queue;	/* 定义一个接收消息的变量 */
	
	while(1)
    {
        xReturn = xQueueReceive( Test_Queue,    /* 消息队列的句柄 */
								&r_queue,      /* 发送的消息内容 */
								portMAX_DELAY); /* 等待时间 一直等(等不到则下面的程序不执行)  ,为0则不等*/   
	
		if(pdTRUE == xReturn)    //接收成功
		{
			OLED_ShowString(3,40,"get",8,1);
		  OLED_Refresh();
		}
	  else                     //接收失败
		{
			OLED_ShowString(3,40,"fal",8,1);
		  OLED_Refresh();
		}
		
		vTaskDelay(100);
    }
}

4-FreeRTOS二值信号量实验

/******************************2023年10月15日*************************************
此为一个二值信号量实验,主要使用使用按键、OLED屏幕来观察现象。
主要创建两个任务一个接收,一个发送
二值信号量,需要按键触发,按下按键则send任务释放二值信号量、LED4翻转;receive获取二值信号量、LED3翻转
receive任务是一直等待,只要send任务释放则receive获取二值信号量。
需定义二值信号量句柄
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.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 SEND_TASK_PRIO		3
//任务堆栈大小	
#define SEND_STK_SIZE 		50  
//任务句柄
TaskHandle_t SendTask_Handler;
//任务函数
void send_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define RECEIVE_TASK_PRIO		4
//任务堆栈大小	
#define RECEIVE_STK_SIZE 		50  
//任务句柄
TaskHandle_t ReceiveTask_Handler;
//任务函数
void receive_task(void *pvParameters);

//创建句柄
SemaphoreHandle_t BinarySem_Handle =NULL;

/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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();           //进入临界区
    
	  /* 创建 BinarySem */
	  BinarySem_Handle = xSemaphoreCreateBinary();
	  
    //创建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); 						
		
		
		//创建接收任务
    xTaskCreate((TaskFunction_t )receive_task,     
                (const char*    )"receive_task",   
                (uint16_t       )RECEIVE_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )RECEIVE_TASK_PRIO,
                (TaskHandle_t*  )&ReceiveTask_Handler);

	//创建发送任务
    xTaskCreate((TaskFunction_t )send_task,     
                (const char*    )"send_task",   
                (uint16_t       )SEND_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )SEND_TASK_PRIO,
                (TaskHandle_t*  )&SendTask_Handler);
								
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=!LED1;
        vTaskDelay(500);
    }
}


void send_task(void *pvParameters)
{   
	
	BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
    while(1)
    {
     if(KEY==1) 
		{
	   xReturn = xSemaphoreGive( BinarySem_Handle );//释放二值信号量
		 if(xReturn==pdPASS) {LED4=!LED4;OLED_ShowString(3,0,"release",8,1);}   //释放成功则LED4反转
		 else OLED_ShowString(3,0,"failed!",8,1);
		}
		else OLED_ShowString(3,0,"nopress",8,1); //没按下时显示"nopress"
		OLED_Refresh();
		vTaskDelay(100);
    }
}

//接收任务函数
void receive_task(void *pvParameters)
{
  BaseType_t xReturn = pdTRUE;/* 定义一个创建信息返回值,默认为pdTRUE */
	
	while(1)
    {
        //获取二值信号量 xSemaphore,没获取到则一直等待
		xReturn = xSemaphoreTake(BinarySem_Handle,/* 二值信号量句柄 */
								portMAX_DELAY); /* 等待时间 */
	
		if(pdTRUE == xReturn)    //获取二值信号量成功
		{
			OLED_ShowString(3,40,"receive",8,1);
			LED3=!LED3;            //获取成功则LED3反转
		}
	  else                     //获取二值信号量失败
		{
			OLED_ShowString(3,40,"nochange",8,1);
		}
		OLED_Refresh();
		vTaskDelay(100);
    }
}

5-FreeRTOS计数信号量实验

/******************************2023年10月15日*************************************
此为一个计数信号量实验,主要使用使用按键、OLED屏幕来观察现象。
主要创建两个任务一个接收,一个发送
计数信号量,需要按键触发,按下按键则send任务释放计数信号量、LED4翻转;receive获取计数信号量、LED3翻转
receive任务是不等待,只要send任务释放则receive才能成功获取二值信号量。
需定义计数信号量句柄
需要修改FreeRTOSConfig.h中的宏定义:
//为1时使用计数信号量
#define configUSE_COUNTING_SEMAPHORES		1
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.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 SEND_TASK_PRIO		3
//任务堆栈大小	
#define SEND_STK_SIZE 		50  
//任务句柄
TaskHandle_t SendTask_Handler;
//任务函数
void send_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define RECEIVE_TASK_PRIO		4
//任务堆栈大小	
#define RECEIVE_STK_SIZE 		50  
//任务句柄
TaskHandle_t ReceiveTask_Handler;
//任务函数
void receive_task(void *pvParameters);

//创建句柄
SemaphoreHandle_t CountSem_Handle =NULL;

/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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();           //进入临界区
    
	/* 创建 CountSem */
	CountSem_Handle = xSemaphoreCreateCounting(5,5);
	  
    //创建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); 						
		
		
		//创建接收任务
    xTaskCreate((TaskFunction_t )receive_task,     
                (const char*    )"receive_task",   
                (uint16_t       )RECEIVE_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )RECEIVE_TASK_PRIO,
                (TaskHandle_t*  )&ReceiveTask_Handler);

	//创建发送任务
    xTaskCreate((TaskFunction_t )send_task,     
                (const char*    )"send_task",   
                (uint16_t       )SEND_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )SEND_TASK_PRIO,
                (TaskHandle_t*  )&SendTask_Handler);
								
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=!LED1;
        vTaskDelay(500);
    }
}


void send_task(void *pvParameters)
{   
	
	BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
    while(1)
    {
     if(KEY==1) 
		{
	   xReturn = xSemaphoreGive( CountSem_Handle );//释放计数信号量
		 if(xReturn==pdPASS) {LED4=!LED4;OLED_ShowString(3,0,"release",8,1);}   //释放成功则LED4反转
		 else OLED_ShowString(3,0,"failed!",8,1);
		}
		else OLED_ShowString(3,0,"nopress",8,1); //没按下时显示"nopress"
		OLED_Refresh();
		vTaskDelay(100);
    }
}

//接收任务函数
void receive_task(void *pvParameters)
{
  BaseType_t xReturn = pdTRUE;/* 定义一个创建信息返回值,默认为pdTRUE */
	
	while(1)
    {
        //获取计数信号量 xSemaphore,没获取到则不等待
		xReturn = xSemaphoreTake(CountSem_Handle,/* 计数信号量句柄 */
								0); /* 等待时间 */
	
		if(pdTRUE == xReturn)    //获取计数信号量成功
		{
			OLED_ShowString(3,40,"receive",8,1);
			LED3=!LED3;            //获取成功则LED3反转
		}
	  else                     //获取计数信号量失败
		{
			OLED_ShowString(3,40,"nochang",8,1);
		}
		OLED_Refresh();
		vTaskDelay(100);
    }
}

6-FreeRTOS互斥信号量实验 - 优先级翻转

/******************************2023年10月17日*************************************
此为一个优先级翻转实验,主要使用使用OLED屏幕来观察现象。
主要创建三个任务高优先级、中优先级、低优先级
模拟优先级翻转、低优先级任务运行时高优先级任务等待
需定义二值信号量句柄
由于高优先级任务需要的资源(二值信号量)被低优先级任务占据,所以无法执行,挂起(此时任务优先级翻转)
中优先级任务没有使用到被占据的资源(二值信号量),所以中优先级任务不用等待低优先级任务执行完毕

需更改宏定义
//使用互斥信号量
#define configUSE_MUTEXES						    1  
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define LED1_TASK_PRIO		3                  //这里提高LED任务优先级,防止低优先级任务阻塞了LED任务
//任务堆栈大小	(单位字)
#define LED1_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define LowPriority_TASK_PRIO		2             //比LED优先级低
//任务堆栈大小	
#define LowPriority_STK_SIZE 		512  
//任务句柄
TaskHandle_t LowPriority_Task_Handle;
//任务函数
void LowPriority_Task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define MidPriority_TASK_PRIO		4
//任务堆栈大小	
#define MidPriority_STK_SIZE 		512  
//任务句柄
TaskHandle_t MidPriority_Task_Handle;
//任务函数
void MidPriority_Task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define HighPriority_TASK_PRIO		5
//任务堆栈大小	
#define HighPriority_STK_SIZE 		512  
//任务句柄
TaskHandle_t HighPriority_Task_Handle;
//任务函数
void HighPriority_Task(void *pvParameters);

//创建句柄
SemaphoreHandle_t BinarySem_Handle =NULL;
/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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)
{   
	  BaseType_t xReturn = pdPASS;
    taskENTER_CRITICAL();           //进入临界区
    
	  /* 创建 BinarySem */
	  BinarySem_Handle = xSemaphoreCreateBinary();
	  xReturn = xSemaphoreGive( BinarySem_Handle );//给出二值信号量	
    //创建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); 						
		
		
		//创建低优先级任务
    xTaskCreate((TaskFunction_t )LowPriority_Task,     
                (const char*    )"LowPriority_Task",   
                (uint16_t       )LowPriority_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LowPriority_TASK_PRIO,
                (TaskHandle_t*  )&LowPriority_Task_Handle);

    //创建中优先级任务
    xTaskCreate((TaskFunction_t )MidPriority_Task,     
                (const char*    )"MidPriority_Task",   
                (uint16_t       )MidPriority_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )MidPriority_TASK_PRIO,
                (TaskHandle_t*  )&MidPriority_Task_Handle);
								
		//创建高优先级任务
    xTaskCreate((TaskFunction_t )HighPriority_Task,     
                (const char*    )"HighPriority_Task",   
                (uint16_t       )HighPriority_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )HighPriority_TASK_PRIO,
                (TaskHandle_t*  )&HighPriority_Task_Handle);
								
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=!LED1;
        vTaskDelay(500);
    }
}


//低优先级任务函数
void LowPriority_Task(void *pvParameters)
{
    BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
	static uint32_t i=0;
	static uint32_t low_see=0;
	while(1)
    {   
        OLED_ShowString(3,0,"low_get",8,1);
			  OLED_Refresh();
		//获取二值信号量 xSemaphore,没获取到则一直等待
		xReturn = xSemaphoreTake(BinarySem_Handle,/* 二值信号量句柄 */
							  portMAX_DELAY); /* 等待时间 */
		if( xReturn == pdTRUE )
		{
			OLED_ShowString(3,0,"low_run",8,1);
			low_see++;
			OLED_ShowNum(60,0,low_see,4,8,1);
		  OLED_Refresh();
			
		}
/*****************************************************************************
此处可以占据二值信号量,导致高优先级任务无法获取二值信号量无法执行。被迫等待低优先级任务执行完毕。
而中优先级任务不需要获取二值信号量所以不受影响
*****************************************************************************/
		for(i=0;i<2000000;i++)//模拟低优先级任务占用信号量
		{
			taskYIELD();//发起任务调度
		}

		OLED_ShowString(3,0,"low_giv",8,1);
		OLED_Refresh();
		xReturn = xSemaphoreGive( BinarySem_Handle );//给出二值信号量
		LED2=!LED2;
		vTaskDelay(500);
    }
}

//中优先级任务函数
void MidPriority_Task(void *pvParameters)
{
	static uint32_t see=0;
	while(1)
    {
		see++;
		OLED_ShowNum(3,20,see,4,8,1);             // 用来证明中优先级任务没有被低优先级任务阻塞         
		OLED_Refresh();
		vTaskDelay(500);
    }
}

//高优先级任务函数
void HighPriority_Task(void *pvParameters)
{
	BaseType_t xReturn = pdTRUE;
	static uint32_t high_see=0;
	while(1)
    {   
		    OLED_ShowString(3,40,"hig_get",8,1);
			  OLED_Refresh();
		//获取二值信号量 xSemaphore,没获取到则一直等待
		xReturn = xSemaphoreTake(BinarySem_Handle,/* 二值信号量句柄 */
                              portMAX_DELAY); /* 等待时间 */
		if(pdTRUE == xReturn)
		{  
  			OLED_ShowString(3,40,"hig_run",8,1);
			  high_see++;
			  OLED_ShowNum(60,40,high_see,4,8,1);
  			OLED_Refresh();    
		}
		LED2=!LED2;
		xReturn = xSemaphoreGive( BinarySem_Handle );//给出二值信号量
		vTaskDelay(500);
    }
}

7-FreeRTOS互斥信号量实验-互斥量

/******************************2023年10月17日*************************************
此为一个互斥信号量实验,主要使用使用OLED屏幕来观察现象。
主要创建三个任务高优先级、中优先级、低优先级
模拟低优先级占用资源、低优先级任务运行时高优先级任务等待
需定义互斥信号量句柄
互斥信号量实验与优先级翻转实验的区别就是:
优先级反转实验定义的是二值信号量,只有需要获取二值信号量的任务会被影响;

互斥信号量实验定义的是互斥信号量,所有的任务都会被影响,体现资源占用互斥

需更改宏定义
//使用互斥信号量
#define configUSE_MUTEXES						    1  
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define LED1_TASK_PRIO		3                  //这里提高LED任务优先级,防止低优先级任务阻塞了LED任务
//任务堆栈大小	(单位字)
#define LED1_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define LowPriority_TASK_PRIO		2             //比LED优先级低
//任务堆栈大小	
#define LowPriority_STK_SIZE 		512  
//任务句柄
TaskHandle_t LowPriority_Task_Handle;
//任务函数
void LowPriority_Task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define MidPriority_TASK_PRIO		4
//任务堆栈大小	
#define MidPriority_STK_SIZE 		512  
//任务句柄
TaskHandle_t MidPriority_Task_Handle;
//任务函数
void MidPriority_Task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define HighPriority_TASK_PRIO		5
//任务堆栈大小	
#define HighPriority_STK_SIZE 		512  
//任务句柄
TaskHandle_t HighPriority_Task_Handle;
//任务函数
void HighPriority_Task(void *pvParameters);

//创建句柄
SemaphoreHandle_t MuxSem_Handle =NULL;
/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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();           //进入临界区
   
	  /* 创建 BinarySem */
    MuxSem_Handle = xSemaphoreCreateMutex();	
    //创建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); 						
		
		
		//创建低优先级任务
    xTaskCreate((TaskFunction_t )LowPriority_Task,     
                (const char*    )"LowPriority_Task",   
                (uint16_t       )LowPriority_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LowPriority_TASK_PRIO,
                (TaskHandle_t*  )&LowPriority_Task_Handle);

    //创建中优先级任务
    xTaskCreate((TaskFunction_t )MidPriority_Task,     
                (const char*    )"MidPriority_Task",   
                (uint16_t       )MidPriority_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )MidPriority_TASK_PRIO,
                (TaskHandle_t*  )&MidPriority_Task_Handle);
								
		//创建高优先级任务
    xTaskCreate((TaskFunction_t )HighPriority_Task,     
                (const char*    )"HighPriority_Task",   
                (uint16_t       )HighPriority_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )HighPriority_TASK_PRIO,
                (TaskHandle_t*  )&HighPriority_Task_Handle);
								
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=!LED1;
        vTaskDelay(500);
    }
}


//低优先级任务函数
void LowPriority_Task(void *pvParameters)
{
    BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
	static uint32_t i=0;
	static uint32_t low_see=0;
	while(1)
    {   
        OLED_ShowString(3,0,"low_get",8,1);
			  OLED_Refresh();
		//获取二值信号量 xSemaphore,没获取到则一直等待
		xReturn = xSemaphoreTake(MuxSem_Handle,/* 互斥信号量句柄 */
							  portMAX_DELAY); /* 等待时间 */
		if( xReturn == pdTRUE )
		{
			OLED_ShowString(3,0,"low_run",8,1);
			low_see++;
			OLED_ShowNum(60,0,low_see,4,8,1);
		  OLED_Refresh();
			
		}
/*****************************************************************************
		模拟低优先级任务占用资源
*****************************************************************************/
		for(i=0;i<2000000;i++)//模拟低优先级任务占用信号量
		{
			taskYIELD();//发起任务调度
		}

		OLED_ShowString(3,0,"low_giv",8,1);
		OLED_Refresh();
		xReturn = xSemaphoreGive( MuxSem_Handle );//给出互斥信号量
		LED2=!LED2;
		vTaskDelay(500);
    }
}

//中优先级任务函数
void MidPriority_Task(void *pvParameters)
{
	static uint32_t see=0;
	while(1)
    {
		see++;
		OLED_ShowNum(3,20,see,4,8,1);             // 用来证明中优先级任务没有被低优先级任务阻塞         
		OLED_Refresh();
		vTaskDelay(500);
    }
}

//高优先级任务函数
void HighPriority_Task(void *pvParameters)
{
	BaseType_t xReturn = pdTRUE;
	static uint32_t high_see=0;
	while(1)
    {   
		    OLED_ShowString(3,40,"hig_get",8,1);
			  OLED_Refresh();
		//获取互斥信号量 xSemaphore,没获取到则一直等待
		xReturn = xSemaphoreTake(MuxSem_Handle,/* 互斥信号量句柄 */
                              portMAX_DELAY); /* 等待时间 */
		if(pdTRUE == xReturn)
		{  
  			OLED_ShowString(3,40,"hig_run",8,1);
			  high_see++;
			  OLED_ShowNum(60,40,high_see,4,8,1);
  			OLED_Refresh();    
		}
		LED2=!LED2;
		xReturn = xSemaphoreGive( MuxSem_Handle );//给出互斥信号量
		vTaskDelay(500);
    }
}

8-FreeRTOS事件实验

/******************************2023年10月17日*************************************
这是一个事件实验,LED2任务需要事件触发,KEY任务可以通过按键计数创建对应的事件,
当事件满足时LED2任务才可以执行一次,执行完之后由于xEventGroupWaitBits某个参数
设置为pdTRUE,所以触发后会自动删除标志位,自动清除。这个函数返回值为事件的计算值。
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.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 		512  
//任务句柄
TaskHandle_t KEYTask_Handler;
//任务函数
void key_task(void *pvParameters);

//创建句柄
EventGroupHandle_t Event_Handle =NULL;

#define KEY1_EVENT  (0x01 << 0)//设置事件掩码的位0
#define KEY2_EVENT  (0x01 << 1)//设置事件掩码的位1
/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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();           //进入临界区
   
	 	/* 创建 Event_Handle */
	 Event_Handle = xEventGroupCreate();	
	
    //创建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();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}

//LED2任务函数
void led2_task(void *pvParameters)
{
    EventBits_t r_event;  /* 定义一个事件接收变量 */
	
	while(1)
    {
        r_event = xEventGroupWaitBits(Event_Handle,  /* 事件对象句柄 */
                                  KEY1_EVENT|KEY2_EVENT,/* 接收线程感兴趣的事件 */
                                  pdTRUE,   /* 退出时清除事件位 */
                                  pdTRUE,   /* 满足感兴趣的所有事件 */
                                  portMAX_DELAY);/* 指定超时事件,一直等 */
                        
		if((r_event & (KEY1_EVENT|KEY2_EVENT)) == (KEY1_EVENT|KEY2_EVENT))
		{
			OLED_ShowString(3,50 ,"get!",8,1);
			LED2=!LED2;
		}
		else
			OLED_ShowString(3,50 ,"err!",8,1);
		
		OLED_Refresh();
    }
}

//KEY任务函数
void key_task(void *pvParameters)
{
   static uint32_t KEY_DOWN=0;
	
	while(1)
    {
		if(KEY==1)
		{
		  KEY_DOWN++;
		  if(KEY_DOWN%2==0) 
			{
			 xEventGroupSetBits(Event_Handle,KEY1_EVENT);         //偶数创建事件1
			 OLED_ShowString(3,0 ,"event1 created!",8,1);
			}
		  else
			{
			 xEventGroupSetBits(Event_Handle,KEY2_EVENT);         //奇数创建事件2
			 OLED_ShowString(3,20 ,"event2 created!",8,1);
		  }
			while(KEY==1);
		}
		  OLED_ShowNum(3,40,KEY_DOWN,2,8,1);
      OLED_Refresh();
		vTaskDelay(20);
    }
}

9-FreeRTOS软件定时器实验

/******************************2023年10月17日*************************************
这是一个软件定时器实验,创建了两个软件定时器,定时器1可以一直定时,定时时间1秒;
定时器2只能定时一次,定时时间5秒。通过OLED屏幕显示来观察定时情况。
1 tick为 1 ms
需要修改宏定义中
 //启用软件定时器
#define configUSE_TIMERS				            1
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.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);

/**************************************************************************************/
//创建句柄
TimerHandle_t Swtmr1_Handle =NULL;
TimerHandle_t Swtmr2_Handle =NULL;

static uint32_t TmrCb_Count1 = 0; /* 记录软件定时器1回调函数执行次数 */
static uint32_t TmrCb_Count2 = 0; /* 记录软件定时器2回调函数执行次数 */

//声明回调函数
static void Swtmr1_Callback(void* parameter);
static void Swtmr2_Callback(void* parameter);


/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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();           //进入临界区
    
	//创建定时器1
	Swtmr1_Handle=xTimerCreate((const char*		)"AutoReloadTimer",
                            (TickType_t			)1000,/* 定时器周期 1000(tick) */
                            (UBaseType_t		)pdTRUE,/* 周期模式 */
                            (void*				  )1,/* 为每个计时器分配一个索引的唯一ID */
                            (TimerCallbackFunction_t)Swtmr1_Callback); /*回调函数名称*/
	if(Swtmr1_Handle != NULL) 
	{
		xTimerStart(Swtmr1_Handle,0);	//开启周期定时器
	}

	//创建定时器2
	Swtmr2_Handle=xTimerCreate((const char*			)"OneShotTimer",
                             (TickType_t			)5000,/* 定时器周期 5000(tick) */
                             (UBaseType_t			)pdFALSE,/* 单次模式 */
                             (void*					  )2,/* 为每个计时器分配一个索引的唯一ID */
                             (TimerCallbackFunction_t)Swtmr2_Callback);  /*回调函数名称*/
	if(Swtmr2_Handle != NULL) 
	{
		xTimerStart(Swtmr2_Handle,0);	//开启周期定时器
	}
							 
    //创建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); 
			
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}

//定时器1回调函数
//软件定时器不要调用阻塞函数,也不要进行死循环,应快进快出
void Swtmr1_Callback(void* parameter)
{		
	TickType_t tick_num1;

	TmrCb_Count1++;						/* 每回调一次加一 */

	tick_num1 = xTaskGetTickCount();	/* 获取滴答定时器的计数值 */

	LED2=!LED2;
  
	OLED_ShowNum(3,0,tick_num1,5,8,1);        //滴答定时器值
	OLED_ShowNum(3,20,TmrCb_Count1,5,8,1);    //软件定时器1值     
	OLED_Refresh();	
}

//定时器2回调函数
//软件定时器不要调用阻塞函数,也不要进行死循环,应快进快出
void Swtmr2_Callback(void* parameter)
{		
	TickType_t tick_num2;

	TmrCb_Count2++;						/* 每回调一次加一 */

	tick_num2 = xTaskGetTickCount();	/* 获取滴答定时器的计数值 */

	OLED_ShowNum(3,40,TmrCb_Count2,5,8,1);    //软件定时器2值
	OLED_ShowNum(3,0,tick_num2,5,8,1);    //滴答定时器值
  OLED_Refresh();	
}

10-FreeRTOS任务通知代替消息队列实验

/******************************2023年10月18日*************************************
这是一个任务通知代替消息队列的实验,通过OLED与KEY观察现象。
判断KEY按下的次数来判断发送哪一个通知,奇数通知接收任务1,偶数通知接收任务2
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.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 Receive1_TASK_PRIO		3
//任务堆栈大小	
#define Receive1_STK_SIZE 		512  
//任务句柄
TaskHandle_t Receive1Task_Handler;
//任务函数
void Receive1_task(void *pvParameters);

//任务优先级
#define Receive2_TASK_PRIO		4
//任务堆栈大小	
#define Receive2_STK_SIZE 		512  
//任务句柄
TaskHandle_t Receive2Task_Handler;
//任务函数
void Receive2_task(void *pvParameters);

//任务优先级
#define Send_TASK_PRIO		5
//任务堆栈大小	
#define Send_STK_SIZE 		512  
//任务句柄
TaskHandle_t SendTask_Handler;
//任务函数
void Send_task(void *pvParameters);

#define  USE_CHAR  0  /* 测试字符串的时候配置为 1 ,测试变量配置为 0  */

/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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); 
	
	//创建Receive1任务
    xTaskCreate((TaskFunction_t )Receive1_task,     
                (const char*    )"Receive1_task",   
                (uint16_t       )Receive1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )Receive1_TASK_PRIO,
                (TaskHandle_t*  )&Receive1Task_Handler);
				
	//创建Receive2任务
    xTaskCreate((TaskFunction_t )Receive2_task,     
                (const char*    )"Receive2_task",   
                (uint16_t       )Receive2_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )Receive2_TASK_PRIO,
                (TaskHandle_t*  )&Receive2Task_Handler);
	
	//创建Send任务
    xTaskCreate((TaskFunction_t )Send_task,     
                (const char*    )"Send_task",   
                (uint16_t       )Send_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )Send_TASK_PRIO,
                (TaskHandle_t*  )&SendTask_Handler);
			
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}

//Receive1任务函数
void Receive1_task(void *pvParameters)
{
    BaseType_t xReturn = pdTRUE;
#if USE_CHAR
  char *r_char;
#else
  uint32_t r_num;
#endif
	
	while(1)
    {
		//获取任务通知 ,没获取到则一直等待
		xReturn=xTaskNotifyWait(0x0,			//进入函数的时候不清除任务bit
								ULONG_MAX,	  //退出函数的时候清除所有的bit
#if USE_CHAR
								(uint32_t *)&r_char,		  //保存任务通知值
#else
								&r_num,		  //保存任务通知值
#endif                        
								portMAX_DELAY);	//阻塞时间
		if( pdTRUE == xReturn )
#if USE_CHAR
			printf("Receive1_Task 任务通知消息为 %s \n",r_char);                      
#else
		  {
		   OLED_ShowString(3,0,"receive1:",8,1);
       OLED_ShowNum(70,0,r_num,1,8,1);	
		   OLED_Refresh();  
      }				
#endif  
		
	  }
}

//Receive2任务函数
void Receive2_task(void *pvParameters)
{
	BaseType_t xReturn = pdTRUE;
#if USE_CHAR
  char *r_char;
#else
  uint32_t r_num;
#endif
	
	while(1)
    {
		//获取任务通知 ,没获取到则一直等待
		xReturn=xTaskNotifyWait(0x0,			//进入函数的时候不清除任务bit
								ULONG_MAX,	  //退出函数的时候清除所有的bit
#if USE_CHAR
								(uint32_t *)&r_char,		  //保存任务通知值
#else
								&r_num,		  //保存任务通知值
#endif                        
								portMAX_DELAY);	//阻塞时间
		if( pdTRUE == xReturn )
#if USE_CHAR
    printf("Receive2_Task 任务通知消息为 %s \n",r_char);
#else   
    {
		 OLED_ShowString(3,20,"receive2:",8,1);
     OLED_ShowNum(70,20,r_num,1,8,1);	
		 OLED_Refresh();
    }			
#endif  
		
	}
}

//Send任务函数
void Send_task(void *pvParameters)
{
	BaseType_t xReturn = pdPASS;
	u8 PRESS=0;
#if USE_CHAR
	char test_str1[] = "this is a mail test 1";/* 邮箱消息test1 */
	char test_str2[] = "this is a mail test 2";/* 邮箱消息test2 */
#else
	uint32_t send1 = 1;
	uint32_t send2 = 2;
#endif
	
	while(1)
	{
		if(KEY==1)
		{ 
			PRESS++;
			while(KEY==1);
/**************************************奇数发送Receive1*****************************************/				
		 if(PRESS%2!=0)
		 {	xReturn = xTaskNotify(Receive1Task_Handler, /*任务句柄*/
#if USE_CHAR 
								(uint32_t)&test_str1, /* 发送的数据,最大为4字节 */
#else
								send1, /* 发送的数据,最大为4字节 */
#endif
								eSetValueWithOverwrite );/*覆盖当前通知*/
			if( xReturn == pdPASS )
			{		
			  OLED_ShowString(3,40,"receive1 send!",8,1);
		    OLED_Refresh();
			}
		}
/***************************************偶数发送Receive2**************************************/		
		else 
		{
			xReturn = xTaskNotify(Receive2Task_Handler, /*任务句柄*/
#if USE_CHAR 
								(uint32_t)&test_str2, /* 发送的数据,最大为4字节 */
#else
								send2, /* 发送的数据,最大为4字节 */
#endif
								eSetValueWithOverwrite );/*覆盖当前通知*/
			if( xReturn == pdPASS )
			{		
			  OLED_ShowString(3,40,"receive2 send!",8,1);
		    OLED_Refresh();
			}
		}
/*****************************************************************************/		
	 }
		vTaskDelay(20);
	}
}

11-FreeRTOS任务通知代替二值信号量实验

/******************************2023年10月18日*************************************
这是一个任务通知代替二值信号量的实验,通过OLED与KEY观察现象。
判断KEY按下的次数来判断发送哪一个通知,奇数通知接收任务1,偶数通知接收任务2
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.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 Receive1_TASK_PRIO		3
//任务堆栈大小	
#define Receive1_STK_SIZE 		512  
//任务句柄
TaskHandle_t Receive1Task_Handler;
//任务函数
void Receive1_task(void *pvParameters);

//任务优先级
#define Receive2_TASK_PRIO		4
//任务堆栈大小	
#define Receive2_STK_SIZE 		512  
//任务句柄
TaskHandle_t Receive2Task_Handler;
//任务函数
void Receive2_task(void *pvParameters);

//任务优先级
#define Send_TASK_PRIO		5
//任务堆栈大小	
#define Send_STK_SIZE 		512  
//任务句柄
TaskHandle_t SendTask_Handler;
//任务函数
void Send_task(void *pvParameters);



/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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); 
	
	//创建Receive1任务
    xTaskCreate((TaskFunction_t )Receive1_task,     
                (const char*    )"Receive1_task",   
                (uint16_t       )Receive1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )Receive1_TASK_PRIO,
                (TaskHandle_t*  )&Receive1Task_Handler);
				
	//创建Receive2任务
    xTaskCreate((TaskFunction_t )Receive2_task,     
                (const char*    )"Receive2_task",   
                (uint16_t       )Receive2_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )Receive2_TASK_PRIO,
                (TaskHandle_t*  )&Receive2Task_Handler);
	
	//创建Send任务
    xTaskCreate((TaskFunction_t )Send_task,     
                (const char*    )"Send_task",   
                (uint16_t       )Send_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )Send_TASK_PRIO,
                (TaskHandle_t*  )&SendTask_Handler);
			
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}

//Receive1任务函数
void Receive1_task(void *pvParameters)
{
	while(1)
    {
		//获取任务通知 ,没获取到则一直等待
		ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
		OLED_ShowString(3,0,"task1 received!",8,1);
		OLED_Refresh();
	}
}

//Receive2任务函数
void Receive2_task(void *pvParameters)
{	
	while(1)
    {
		//获取任务通知 ,没获取到则一直等待
		ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
		OLED_ShowString(3,20,"task2 received!",8,1);
		OLED_Refresh();
	  }
}

//Send任务函数
void Send_task(void *pvParameters)
{
	BaseType_t xReturn = pdPASS;
	u8 PRESS=0;

	while(1)
	{
		if(KEY==1)
		{ 
			PRESS++;
			while(KEY==1);
/**************************************奇数发送Receive1*****************************************/				
		 if(PRESS%2!=0)
		 {				
			  xReturn = xTaskNotifyGive(Receive1Task_Handler);
			  if( xReturn == pdTRUE )
				{
				OLED_ShowString(3,40,"task1 send!",8,1);
		    OLED_Refresh();
				}
		 }
/***************************************偶数发送Receive2**************************************/		
		else 
		{
        xReturn = xTaskNotifyGive(Receive2Task_Handler);
			  if( xReturn == pdTRUE )
				{
				OLED_ShowString(3,40,"task2 send!",8,1);
		    OLED_Refresh();
				}
		}
/*****************************************************************************/		
	 }
		vTaskDelay(20);
	}
}

12-FreeRTOS任务通知代替计数信号量实验

/******************************2023年10月18日*************************************
这是一个任务通知代替计数信号量的实验,通过OLED与KEY观察现象。
KEY按下释放信号量,长按可一直释放信号量
take任务会一直获取信号量
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.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 Take_TASK_PRIO		3
//任务堆栈大小	
#define Take_STK_SIZE 		512  
//任务句柄
TaskHandle_t TakeTask_Handler;
//任务函数
void Take_task(void *pvParameters);

//任务优先级
#define Give_TASK_PRIO		4
//任务堆栈大小	
#define Give_STK_SIZE 		512  
//任务句柄
TaskHandle_t GiveTask_Handler;
//任务函数
void Give_task(void *pvParameters);



/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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); 
	
	//创建Take任务
    xTaskCreate((TaskFunction_t )Take_task,     
                (const char*    )"Take_task",   
                (uint16_t       )Take_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )Take_TASK_PRIO,
                (TaskHandle_t*  )&TakeTask_Handler);
				
	//创建Give任务
    xTaskCreate((TaskFunction_t )Give_task,     
                (const char*    )"Give_task",   
                (uint16_t       )Give_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )Give_TASK_PRIO,
                (TaskHandle_t*  )&GiveTask_Handler);
			
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}

//Give任务函数
void Give_task(void *pvParameters)
{	
	BaseType_t xReturn = pdPASS;

	while(1)
	{
		if(KEY==1)
		{
			xReturn=xTaskNotifyGive(TakeTask_Handler);//发送任务通知
			if ( pdPASS == xReturn ) 
			{ 
				OLED_ShowString(3,0,"release one!",8,1);
			  OLED_Refresh();
			}
		}
		vTaskDelay(20);
	}
}

//Take任务函数
void Take_task(void *pvParameters)
{
	uint32_t take_num = pdTRUE;
	
	while(1)
	{
			take_num=ulTaskNotifyTake(pdFALSE,0);
			if(take_num > 0)
			  OLED_ShowNum(3,20,take_num,4,8,1);
			else
				OLED_ShowString(3,40,"wait",8,1); 
			OLED_Refresh();
	
		vTaskDelay(20);
	}
}

13-FreeRTOS任务通知代替事件组实验

/******************************2023年10月18日*************************************
这是一个任务通知代替事件组的实验,通过OLED与KEY观察现象。
KEY按下计数,通过计数的奇偶值来判断产生哪一个事件
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.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 		512  
//任务句柄
TaskHandle_t KEYTask_Handler;
//任务函数
void key_task(void *pvParameters);


#define KEY1_EVENT  (0x01 << 0)//设置事件掩码的位0
#define KEY2_EVENT  (0x01 << 1)//设置事件掩码的位1




/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}

//LED2任务函数
void led2_task(void *pvParameters)
{
    BaseType_t xReturn = pdTRUE;
	uint32_t r_event = 0;  /* 定义一个事件接收变量 */
	uint32_t last_event = 0;/* 定义一个保存事件的变量 */
	
	while(1)
    {
        //获取任务通知 ,没获取到则一直等待
		xReturn = xTaskNotifyWait(0x0,			//进入函数的时候不清除任务bit
								ULONG_MAX,	  //退出函数的时候清除所有的bitR
								&r_event,		  //保存任务通知值                    
								portMAX_DELAY);	//阻塞时间
                        
		if( pdTRUE == xReturn )
		{
			last_event |= r_event;
			if(last_event == (KEY1_EVENT|KEY2_EVENT))
			{
				last_event=0;
				LED2=!LED2;
			}
			else
				last_event = r_event;
		}
    }
}

//KEY任务函数
void key_task(void *pvParameters)
{
    u8 PRESS=0;
	while(1)
    {
		if(KEY==1)
		{ 
			PRESS++;
			while(KEY==1);      
			if(PRESS%2!=0)          
			{
       OLED_ShowString(3,0,"KEY1_EVENT!",8,1);
			 /* 触发一个事件1 */
			 xTaskNotify((TaskHandle_t	)LED2Task_Handler,//接收任务通知的任务句柄
						(uint32_t		)KEY1_EVENT,//要触发的事件
						(eNotifyAction)eSetBits);//设置任务通知值中的位
			}
			else
			{
			 OLED_ShowString(3,20,"KEY2_EVENT!",8,1);
			 /* 触发一个事件2 */
			 xTaskNotify((TaskHandle_t	)LED2Task_Handler,//接收任务通知的任务句柄
						(uint32_t		)KEY2_EVENT,//要触发的事件
						(eNotifyAction)eSetBits);//设置任务通知值中的位
			}
		 }
		OLED_Refresh();
		vTaskDelay(20);
    }
}

14-FreeRTOS内存管理实验

/******************************2023年10月18日*************************************
这是一个内存管理实验,通过OLED与KEY观察现象。
KEY按下计数,通过计数的奇偶值来判断产生申请内存还是释放内存
显示申请到的内存地址,以及申请内存后的剩余空间,以及系统运行时间
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.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 KEY_TASK_PRIO		4
//任务堆栈大小	
#define KEY_STK_SIZE 		512  
//任务句柄
TaskHandle_t KEYTask_Handler;
//任务函数
void key_task(void *pvParameters);


uint8_t *Test_Ptr = NULL;




/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	//创建开始任务
    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); 
	
	//创建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();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}


//KEY任务函数
void key_task(void *pvParameters)
{
    u8 PRESS=0;
	uint32_t g_memsize;
	
	while(1)
    {
		if(KEY==1)
		{
			while(KEY==1);
			PRESS++;
			if(PRESS%2!=0)
			{
			 if(NULL == Test_Ptr)
			{
				/* 获取当前内存大小 */
				g_memsize = xPortGetFreeHeapSize();   
				OLED_ShowString(3,0,"rest ram:",8,1);
				OLED_ShowNum(60,0,g_memsize,9,8,1);
				Test_Ptr = pvPortMalloc(1024);              //申请1k内存
				if(NULL != Test_Ptr)
				{
				 OLED_ShowString(3,20,"get ram:",8,1);
	       sprintf((char*)Test_Ptr," %#x \n",Test_Ptr);     //转变为16进制数据
				 OLED_ShowString(60,20,(char*)Test_Ptr,8,1);	   //显示地址

					/* 获取当前内剩余存大小 */
				 g_memsize = xPortGetFreeHeapSize();
				 OLED_ShowString(3,40,"rest ram:",8,1);
				 OLED_ShowNum(60,40,g_memsize,9,8,1);
						  
					//向Test_Ptr中写入当数据:当前系统时间
					sprintf((char*)Test_Ptr,"TickCount = %d \n",xTaskGetTickCount());
//					printf("写入的数据是 %s \n",(char*)Test_Ptr);
					OLED_ShowString(3,50,(char*)Test_Ptr,8,1);
				}
			}
			else
				printf("请先按下KEY2释放内存再申请\n");
			}
			else
		  {
			 		if(NULL != Test_Ptr)
			{ 
				OLED_Clear();
				OLED_ShowString(3,0,"clear ram",8,1);
				vPortFree(Test_Ptr);//释放内存
				Test_Ptr=NULL;
				/* 获取当前内剩余存大小 */
				g_memsize = xPortGetFreeHeapSize();
				OLED_ShowString(3,20,"rest ram:",8,1);
				OLED_ShowNum(60,20,g_memsize,9,8,1);
			}
			else
				printf("请先按下KEY1申请内存再释放\n");
			}
		 }
	    OLED_Refresh();
		vTaskDelay(20);
    }
}

15-FreeRTOS-CPU利用率实验

/******************************2023年10月18日*************************************
这是一个CPU利用率实验,通过USART1与XCOM观察现象。
串口会不断的打印CPU利用情况
本次需要使用硬件定时器来统计CPU运行时间,频率为10000HZ
需修改配置文件如下内容

/********************************************************************
          FreeRTOS与运行时间和任务状态收集有关的配置选项   
**********************************************************************/
//启用运行时间统计功能
//#define configGENERATE_RUN_TIME_STATS	        1             
 //启用可视化跟踪调试
//#define configUSE_TRACE_FACILITY				      1    
/* 与宏configUSE_TRACE_FACILITY同时为1时会编译下面3个函数
 * prvWriteNameToBuffer()
 * vTaskList(),
 * vTaskGetRunTimeStats()
*/
//#define configUSE_STATS_FORMATTING_FUNCTIONS	1                       
//                                                                        
//     extern volatile uint32_t CPU_RunTime;

//#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()     (CPU_RunTime = 0ul)
//#define portGET_RUN_TIME_COUNTER_VALUE()              CPU_RunTime  

*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.h"
#include "timer.h"
#include "string.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 CPU_TASK_PRIO		4
//任务堆栈大小	
#define CPU_STK_SIZE 		512  
//任务句柄
TaskHandle_t CPUTask_Handler;
//任务函数
void CPU_task(void *pvParameters);
/************************************************************/



/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	TIM2_Int_Init(100-1,72-1);
	printf("Freertos CPU利用率实验\r\n");
	//创建开始任务
    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);
	
	//创建CPU任务
    xTaskCreate((TaskFunction_t )CPU_task,     
                (const char*    )"CPU_task",   
                (uint16_t       )CPU_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )CPU_TASK_PRIO,
                (TaskHandle_t*  )&CPUTask_Handler);
			
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
		printf("LED1_Task Running,LED2_ON\r\n");
        LED1=1;
        vTaskDelay(800);
		printf("LED1_Task Running,LED2_OFF\r\n");
    }
}

//LED2任务函数
void led2_task(void *pvParameters)
{
    while(1)
    {
        LED2=0;
        vTaskDelay(800);
		printf("LED2_Task Running,LED2_ON\r\n");
        LED2=1;
        vTaskDelay(200);
		printf("LED2_Task Running,LED2_OFF\r\n");
    }
}

//CPU任务函数
void CPU_task(void *pvParameters)
{
    uint8_t CPU_RunInfo[400];//保存任务运行时间信息
	
	while(1)
    {
		memset(CPU_RunInfo,0,400);//信息缓冲区清零
		vTaskList((char *)&CPU_RunInfo);  //获取任务运行时间信息
		
		printf("---------------------------------------------\r\n");
		printf("任务名      任务状态 优先级   剩余栈 任务序号\r\n");
		printf("%s", CPU_RunInfo);
		printf("---------------------------------------------\r\n");

		memset(CPU_RunInfo,0,400);				//信息缓冲区清零

		vTaskGetRunTimeStats((char *)&CPU_RunInfo);

		printf("任务名       运行计数         利用率\r\n");
		printf("%s", CPU_RunInfo);
		printf("---------------------------------------------\r\n\n");
		vTaskDelay(1000);   /* 延时1000个tick */
    }
}

16-FreeRTOS中断管理实验

/******************************2023年10月18日*************************************
这是一个中断管理实验,通过设置中断优先级来起到控制作用。
freertos中断开关管理可以管理优先级低的
中断优先级数值越小,优先级越高。
默认中断管理阈值为5,优先级数值高于或等于5的中断可以被管理
任务优先级数值小于5的中断不会被管理,因为优先级更高。
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.h"
#include "timer.h"
#include "string.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 		512 
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);


//任务优先级
#define Interrupt_TASK_PRIO		4
//任务堆栈大小	
#define Interrupt_STK_SIZE 		512  
//任务句柄
TaskHandle_t InterruptTask_Handler;
//任务函数
void Interrupt_task(void *pvParameters);


extern volatile uint32_t TIME2_RUN;
extern volatile uint32_t TIME3_RUN;
/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
int main()
{
	SysTick_Init(72);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
	USART1_Init(115200);
	KEY_Init();
	LED_Init();
	OLED_Init();
	OLED_ColorTurn(0);//0正常显示,1 反色显示             
  OLED_DisplayTurn(0);
	OLED_Clear();
	TIM2_Int_Init(10000-1,7200-1);     //1s中断
	TIM3_Int_Init(10000-1,7200-1);     //1s中断
	printf("Freertos CPU利用率实验\r\n");
	//创建开始任务
    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); 
	
	 //创建Interrupt任务
    xTaskCreate((TaskFunction_t )Interrupt_task,     
                (const char*    )"Interrupt_task",   
                (uint16_t       )Interrupt_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )Interrupt_TASK_PRIO,
                (TaskHandle_t*  )&InterruptTask_Handler);
			
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
} 

//LED1任务函数
void led1_task(void *pvParameters)
{   
    while(1)
    {
			OLED_ShowNum(3,0,TIME3_RUN,4,8,1);
			OLED_ShowNum(3,20,TIME2_RUN,4,8,1);
			OLED_Refresh();
      vTaskDelay(200);
    }
}

//Interrupt任务函数
void Interrupt_task(void *pvParameters)
{
    static u32 total_num=0;
	
	while(1)
    {
		total_num+=1; 
		if(total_num==5)
		{
			printf("关闭中断.............\r\n");
			portDISABLE_INTERRUPTS(); //关闭中断
			delay_xms(6000); //延时6s,使用不影响任务调度的延时
			printf("打开中断.............\r\n"); //打开中断
			portENABLE_INTERRUPTS();
		}
		LED2=!LED2;
		vTaskDelay(1000);
    }
}

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值