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://www.pswp.cn/web/9857.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/9857.shtml
英文地址,請注明出處:http://en.pswp.cn/web/9857.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C語言編程中布爾設置位掩碼示例

在C語言編程中&#xff0c;當你想使用整數&#xff08;通常是unsigned int或uint8_t, uint16_t, uint32_t等&#xff09;的位來存儲多個布爾設置時&#xff0c;你會使用位掩碼。每個設置對應于整數中的一個位&#xff0c;你可以通過位操作&#xff08;如按位與&、按位或|、…

Rust:用 Warp 庫實現 Restful API 的簡單示例

直接上代碼&#xff1a; 1、源文件 Cargo.toml [package] name "xcalc" version "0.1.0" edition "2021"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies] warp "…

uniap之微信公眾號支付

近來用uniapp開發H5的時候&#xff0c;需要接入支付&#xff0c;原來都是基于后端框架來做的&#xff0c;所以可謂是一路坑中過&#xff0c;今天整理下大致流程分享給大家。 先封裝util.js&#xff0c;便于后面調用 const isWechat function(){return String(navigator.userA…

隊列的實現(使用C語言)

完整代碼鏈接&#xff1a;DataStructure: 基本數據結構的實現。 (gitee.com) 目錄 一、隊列的概念&#xff1a; 二、隊列的實現&#xff1a; 使用鏈表實現隊列&#xff1a; 1.結構體設計&#xff1a; 2.初始化&#xff1a; 3.銷毀&#xff1a; 4.入隊&#xff1a; 5.…

OC foudation框架(下)的學習

OCfoudation框架&#xff08;下&#xff09; 前面學習了有關OCfoudation框架的部分內容&#xff0c;我們現在對于后面的內容繼續學習。 文章目錄 OCfoudation框架&#xff08;下&#xff09;數組&#xff08;NSArray和NSMutableArray&#xff09;對集合元素整體調用方法排序使用…

會賺錢的人都在做這件事:你了解嗎?

在我們日常生活的點滴中&#xff0c;以及在各種場合的交互中&#xff0c;利他思維始終扮演著不可或缺的角色。當我們追求合作與共贏時&#xff0c;單方面的自我立場顯然是不夠的&#xff0c;真正的關鍵在于換位思考&#xff0c;尋找并滿足對方的需求。 互利互贏的核心理念正是利…

設置docker容器時區

設置docker容器時區 查看當前系統時間 1.1 查看當前系統版本 cat /etc/issue1.2 查看當前系統時間 date查看鏡像默認時間 2.1 alpine鏡像 sudo docker run -it --rm alpine date2.2 ubuntu鏡像 sudo docker run -it --rm ubuntu date2.3 centos鏡像 sudo docker run -it --rm …

虛擬知識付費系統源碼推薦,在線教育雙十一怎么做活動?

又是一年光棍節&#xff0c;啊不是&#xff0c;剁手節。小伙伴們早就摩拳擦掌準備剁手了&#xff0c;這個時候&#xff0c;幾乎所有線上平臺都行動起來了&#xff0c;而在線教育行業也沒有閑著。如今&#xff0c;雙十一已經成為了各大在線教育公司用來變現的一個大殺器&#xf…

ruoyi-vue-pro 使用記錄(4)

ruoyi-vue-pro 使用記錄&#xff08;4&#xff09; CRM數據庫線索客戶商機合同回款產品其他 CRM 文檔 主要分為 6 個核心模塊&#xff1a;線索、客戶、商機、合同、回款、產品。 線索管理以 crm_clue 作為核心表客戶管理以 crm_customer 作為核心表商機管理以 crm_business 作…

JavaScript數組(Array)方法 - toReversed、toSorted、toSpliced

最近發現幾個數組方法&#xff0c;是一些常規方法的升級版&#xff0c;比較有意思&#xff0c;分享給大家 文章目錄 一、溫故二、知新toReversedtoSortedtoSpliced 一、溫故 我們先來回顧幾個比較常用的方法&#xff1a;reverse&#xff0c;sort&#xff0c;splice眾所周知&a…

luceda ipkiss教程 69:導出器件或者線路的三維模型

ipkiss 3.12版加入write_obj函數&#xff0c;可以直接輸出器件的三維模型。 如&#xff0c;輸出自定義的mmi的三維模型&#xff1a; 代碼如下&#xff1a; from si_fab import all as pdk from ipkiss3 import all as i3class MMI1x2(i3.PCell):"""MMI with …

kaldi學習參考

HMM模型 https://www.cnblogs.com/baixf-xyz/p/16777438.htmlhttps://www.cnblogs.com/baixf-xyz/p/16777438.htmlGMM-HMM 基于GMM-HMM的語音識別系統https://www.cnblogs.com/baixf-xyz/p/16777439.html https://www.cnblogs.com/baixf-xyz/p/16777426.htmlhttps://www.cnbl…

全棧開發之路——前端篇(6)生命周期和自定義hooks

全棧開發一條龍——前端篇 第一篇&#xff1a;框架確定、ide設置與項目創建 第二篇&#xff1a;介紹項目文件意義、組件結構與導入以及setup的引入。 第三篇&#xff1a;setup語法&#xff0c;設置響應式數據。 第四篇&#xff1a;數據綁定、計算屬性和watch監視 第五篇 : 組件…

碼一點網站

Linux命令查詢網站 https://www.lzltool.com/LinuxCommand/Index 小林 x 圖解計算機基礎 https://xiaolincoding.com/ 代碼隨想錄 https://programmercarl.com/ 可用于爬蟲 https://books.toscrape.com/ 數據結構可視化 https://www.cs.usfca.edu/~galles/visualization/ …

fastText-文本分類

fastText介紹 fastText是一個快速文本分類算法,與基于神經網絡的分類算法相比有兩大優點: 1、fastText在保持高精度的情況下加快了訓練速度和測試速度 2、fastText不需要預訓練好的詞向量,fastText會自己訓練詞向量 3、fastText兩個重要的優化:Hierarchical Softmax、N-gr…

387.字符串中的第一個唯一字符

刷算法題&#xff1a; 第一遍&#xff1a;1.看5分鐘&#xff0c;沒思路看題解 2.通過題解改進自己的解法&#xff0c;并且要寫每行的注釋以及自己的思路。 3.思考自己做到了題解的哪一步&#xff0c;下次怎么才能做對(總結方法) 4.整理到自己的自媒體平臺。 5.再刷重復的類…

YUV中Y顏色模型的采樣

YUV的特點 相對于表示顏色的GUI&#xff0c; YUI將亮度&#xff08;用Y表示&#xff09;與色調&#xff08;用U和V表示&#xff09;分開來表示。又因為人類視網膜上的視網膜桿細胞要多于視網膜錐細 胞&#xff0c;說得通俗一些&#xff0c;視網膜桿細胞的作用就是識別亮度&…

LabVIEW MEMS電容式壓力傳感器測試系統

LabVIEW MEMS電容式壓力傳感器測試系統 隨著微電子技術的發展&#xff0c;MEMS&#xff08;微電機系統&#xff09;技術在各個領域得到了廣泛應用。MEMS電容式壓力傳感器以其高靈敏度、小尺寸、低功耗等優點&#xff0c;在微傳感器領域占據了重要的地位。然而&#xff0c;這些…

Smma-net:一種基于音頻線索的目標說話人提取網絡,具有譜圖匹配和相互關注功能

SMMA-NET: AN AUDIO CLUE-BASED TARGET SPEAKER EXTRACTION NETWORK WITH SPECTROGRAM MATCHING AND MUTUAL ATTENTION 第二章 目標說話人提取之《Smma-net:一種基于音頻線索的目標說話人提取網絡&#xff0c;具有譜圖匹配和相互關注功能》 文章目錄 SMMA-NET: AN AUDIO CLUE-…

程序員的多維智慧:技術修煉、人際交往與投資哲學

程序員不應該只會埋頭敲代碼&#xff0c;要多看看書&#xff0c;多學習... 1.程序員技術 保持嚴謹的作風&#xff0c;實事求是&#xff0c;記錄現象&#xff0c;找準依據&#xff0c;可以做出假設&#xff0c;問題的解釋和結論必須能完整、全面符合現象和各種認知邏輯。 絕不…