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);//设置系统中断优先级分组4LED_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);//设置系统中断优先级分组4LED_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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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;}elseOLED_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);         //偶数创建事件1OLED_ShowString(3,0 ,"event1 created!",8,1);}else{xEventGroupSetBits(Event_Handle,KEY2_EVENT);         //奇数创建事件2OLED_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);//设置系统中断优先级分组4USART1_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();           //进入临界区//创建定时器1Swtmr1_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);	//开启周期定时器}//创建定时器2Swtmr2_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);//设置系统中断优先级分组4USART1_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_CHARchar *r_char;
#elseuint32_t r_num;
#endifwhile(1){//获取任务通知 ,没获取到则一直等待xReturn=xTaskNotifyWait(0x0,			//进入函数的时候不清除任务bitULONG_MAX,	  //退出函数的时候清除所有的bit
#if USE_CHAR(uint32_t *)&r_char,		  //保存任务通知值
#else&r_num,		  //保存任务通知值
#endif                        portMAX_DELAY);	//阻塞时间if( pdTRUE == xReturn )
#if USE_CHARprintf("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_CHARchar *r_char;
#elseuint32_t r_num;
#endifwhile(1){//获取任务通知 ,没获取到则一直等待xReturn=xTaskNotifyWait(0x0,			//进入函数的时候不清除任务bitULONG_MAX,	  //退出函数的时候清除所有的bit
#if USE_CHAR(uint32_t *)&r_char,		  //保存任务通知值
#else&r_num,		  //保存任务通知值
#endif                        portMAX_DELAY);	//阻塞时间if( pdTRUE == xReturn )
#if USE_CHARprintf("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_CHARchar test_str1[] = "this is a mail test 1";/* 邮箱消息test1 */char test_str2[] = "this is a mail test 2";/* 邮箱消息test2 */
#elseuint32_t send1 = 1;uint32_t send2 = 2;
#endifwhile(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字节 */
#elsesend1, /* 发送的数据,最大为4字节 */
#endifeSetValueWithOverwrite );/*覆盖当前通知*/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字节 */
#elsesend2, /* 发送的数据,最大为4字节 */
#endifeSetValueWithOverwrite );/*覆盖当前通知*/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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);elseOLED_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);//设置系统中断优先级分组4USART1_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,			//进入函数的时候不清除任务bitULONG_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;}elselast_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);//设置系统中断优先级分组4USART1_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);}}elseprintf("请先按下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);}elseprintf("请先按下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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3029552.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

基础算法,贪心算法,贪心策略,OJ练习

文章目录 一、概念二、OJ练习2.1 区间选点2.2 区间合并2.3 区间2.4 合并果子2.5 排队接水2.6 货仓选址2.7 防晒2.8 畜栏预定2.9 雷达设备2.10 国王游戏2.11 耍杂技的牛2.12 给树染色2.13 任务2.14 能量石 三、总结 一、概念 贪心是一种在每次决策时采取当前意义下最优策略的算…

MDK/keil高阶使用手册

1.开启watch和内存窗口的值实时更新 2.调试模式可以查看局部变量的值 只不过要让任意被观察变量退出<cannot evaluate>状态,都需要先在该变量被赋值的地方先打个断点,此后该变量的值就能实时更新了。 3.可以在watch窗口直接输入你要查看的变量的名称 4.可以在watch窗…

iframe的替代方案有吗?做页面嵌套界面套娃

UIOTOS可以了解下&#xff0c;uiotos.net&#xff0c;通过连线来代替脚本逻辑开发&#xff0c;复杂的交互界面&#xff0c;通过页面嵌套轻松解决&#xff0c;是个很新颖的思路&#xff0c;前端零代码&#xff01; 蓝图连线尤其是独创的页面嵌套和属性继承技术&#xff0c;好家…

敏感信息提取插件-CaA(三)

0x01 简介 CaA是一个基于BurpSuite Java插件API开发的流量收集和分析插件。它的主要作用就是收集HTTP协议报文中的参数、路径、文件、参数值等信息&#xff0c;并统计出现的频次&#xff0c;为使用者积累真正具有实战意义的Fuzzing字典。除此之外&#xff0c;CaA还提供了独立的…

SMI接口

目录 SMI 接口帧格式读时序写时序 IP 设计IP 例化界面IP 接口IP 验证 SMI 接口 SMI&#xff08;Serial Management Interface&#xff09;串行管理接口&#xff0c;也被称作 MII 管理接口&#xff08;MII Management Interface&#xff09;&#xff0c;包括 MDC 和 MDIO 两条信…

system函数和popen函数

system函数 #include <stdlib.h> *int system(const char command); system函数在linux中的源代码&#xff1a; int system(const char * cmdstring) {pid_t pid;int status;if(cmdstring NULL){return (1);}if((pid fork())<0){status -1;}else if(pid 0){ //子…

翻工第二次 Ant Design Pro 下载,发现问题,电脑网络配置有误,魔法了

一、相关网址链接 鱼皮的用户中心项目 &#xff08;前端Ant Design Pro构建&#xff09; 语雀 ## 没有选择umi版本这一步 Issue #11144 ant-design/ant-design-pro GitHub 关于umi ui图标未显示问题_umi ui不出现-CSDN博客 二、存在问题 导致下载速度慢 本人镜像代码写…

TDN: Temporal Difference Networks for Efficient Action Recognition 论文阅读

TDN: Temporal Difference Networks for Efficient Action Recognition 论文阅读 Abstract1. Introduction2. Related work3. Temporal Difference Networks3.1. Overview3.2. Short-term TDM3.3. Long-term TDM3.4. Exemplar: TDN-ResNet 4. ExperimentsAblation studiesCompa…

【计算机毕业设计】springboot工资管理系统

人类现已迈入二十一世纪&#xff0c;科学技术日新月异&#xff0c;经济、资讯等各方面都有了非常大的进步&#xff0c;尤其是资讯与 网络技术的飞速发展&#xff0c;对政治、经济、军事、文化等各方面都有了极大的影响。 利用电脑网络的这些便利&#xff0c;发展一套工资管理系…

深度剖析:SSD能否全面取代HDD?-2

近日&#xff0c;希捷针对SSD即将全面取代HDD的市场预言也提出站在HDD厂商角度不同的观点。 这些观点出自希捷的一份演示文稿&#xff0c;实质上是对Pure Storage首席执行官Charlie Giancarlo所称“五年内不会再有新的磁盘系统出售”这一论断的回应&#xff0c;意味着到2028年底…

JavaScript使用 BigInt

在 JavaScript 中&#xff0c;最大的安全整数是 2 的 53 次方减 1&#xff0c;即 Number.MAX_SAFE_INTEGER&#xff0c;其值为 9007199254740991。这是因为 JavaScript 中使用双精度浮点数表示数字&#xff0c;双精度浮点数的符号位占 1 位&#xff0c;指数位占 11 位&#xff…

Transformers中加载预训练模型的过程剖析

使用HuggingFace的Transformers库加载预训练模型来处理下游深度学习任务很是方便,然而加载预训练模型的方法多种多样且过程比较隐蔽,这在一定程度上会给人带来困惑。因此,本篇文章主要讲一下使用不同方法加载本地预训练模型的区别、加载预训练模型及其配置的过程,藉此做个记…

PXE批量部署,一键安装配置多台Linux系统

目录 一、PXE批量部署的优点 二、搭建PXE远程安装服务器 1. 实验初始化设置 2. 一键安装软件包 3. 复制 vmlinuz、initrd.img、pxelinux.0文件 4. 配置PE启动菜单配置文件 5. 修改配置文件&#xff0c; 启动各个软件服务 6. kickstart自动应答文件修改启动菜单配置文件…

CSCWD 2024会议最后一天 女高音惊艳全场,相声笑破肚皮

会议之眼 快讯 今天是第27届国际计算机协同计算与设计大会&#xff08;CSCWD 2024&#xff09;举办的最后一天&#xff01;会议依然热络&#xff0c;紧张而充实&#xff01;各个技术分论坛持续展开&#xff0c;学者们的热情不减&#xff0c;对技术领域的热爱和探索精神令人赞叹…

测试环境搭建整套大数据系统(十六:超级大文件处理遇到的问题)

一&#xff1a;yarn出现损坏的nodemanger 报错现象 日志&#xff1a;1/1 local-dirs usable space is below configured utilization percentage/no more usable space [ /opt/hadoop-3.2.4/data/nm-local-dir : used space above threshold of 90.0% ] ; 1/1 log-dirs usabl…

文件批量重命名技巧:文本内容即文件名,打造个性化文件命名新体验

在日常工作和学习中&#xff0c;我们经常需要处理大量的文件&#xff0c;而给这些文件命名则成为了一个既繁琐又重要的任务。传统的文件命名方式&#xff0c;如使用数字、字母或简单的描述性词汇&#xff0c;往往难以体现出文件的实际内容和特点。那么&#xff0c;有没有一种方…

不同阶层在韩留学生的生活差距,柯桥留学韩语培训

有很多同学问韩国留学花费是多少&#xff0c;楼主一般都会回答每年12-15万左右&#xff0c;这是一个平均数&#xff0c;也是大部分学生的花费。 但如果按真实情况来说&#xff0c;可能是0~100万&#xff0c;因为每名同学的家庭经济情况不同&#xff0c;花费完全看家里给多少&am…

【面试必备】Java基础80问-个人摘记

Java基础80问 1. 说说&和&&的区别 &和&&都可以用作逻辑与的运算符。&&还具有短路的功能&#xff0c;即如果第一个表达式为false&#xff0c;则不再计算第二个表达式&#xff1b;&还可以用作位运算符&#xff0c;当&操作符两边的表达…

官宣:vAsterNOS正式发布!开放网络操作系统免费试用!

近期&#xff0c;vAsterNOS&#xff08;设备模拟器&#xff09;正式发布&#xff0c;可以满足用户快速了解 AsterNOS、体验实际操作、搭建模拟网络的需求&#xff0c;可运行在GNS3、EVE-NG等网络虚拟软件中。 AsterNOS 网络操作系统是星融元为人工智能、机器学习、高性能计算、…

HarmonyOS开发案例:【生活健康app之编写通用工具类】(5)

本节将介绍日志打印、时间换算等通用工具类的编写和使用&#xff0c;工具类可以简化应用代码编写和业务流程处理。 日志类 日志类Logger旨在提供一个全局的日志打印、日志管理的地方&#xff0c;既可以规范整个应用的日志打印&#xff0c;也方便日后对日志工具类进行修改&…