FreeRTOS學習
1、動態創建任務
#include "main.h"
#include "driver_led.h"
#include "driver_key.h"
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL庫函數必須要調用此函數
HAL_Init();
// 系統時鐘即AHB/APB時鐘配置
SystemClock_Config();
// 初始化LED
LedGpioInit();
KeyInit();
FreeRTOS_Start();
}
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
TaskHandle_t task3_handle;
void StartTask(void);
void Task1(void);
void Task2(void);
void Task3(void);
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任務函數的地址
(char *) "StartTask", //任務函數的名稱
(uint16_t) 128, //任務函數??臻g大小
(void *) NULL, //任務函數的參數
(UBaseType_t) 1, //任務函數的優先級
(TaskHandle_t*) &start_task_handle //任務函數的句柄
);
//啟動調度器
vTaskStartScheduler();
}
void StartTask(void)
{
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 2,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task2_handle
);
xTaskCreate(
(TaskFunction_t) Task3,
(char *) "Task3",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task3_handle
);
vTaskDelete(NULL);
taskEXIT_CRITICAL();
}
void Task1(void)
{
while(1)
{
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
vTaskDelay(500);
}
}
void Task2(void)
{
while(1)
{
LED_TOGGLE(LED1_GPIO_PORT,LED1_GPIO_PIN);
vTaskDelay(500);
}
}
void Task3(void)
{
while(1)
{
if(KeyScan() == 0)
{
if(task1_handle != NULL) vTaskDelete(task1_handle);
task1_handle = NULL;
}
vTaskDelay(500);
}
}
2、靜態創建任務
#include "main.h"
#include "driver_led.h"
#include "driver_key.h"
/* 啟動任務的配置 */
#define START_TASK_STACK 128
#define START_TASK_PRIORITY 1
TaskHandle_t start_task_handle;
StackType_t start_task_stack[START_TASK_STACK]; // 靜態任務的任務棧,以數組形式存儲
StaticTask_t start_task_tcb; // 靜態任務的TCB結構體類型
void start_task(void);
/* 任務1的配置 */
#define TASK1_STACK 128
#define TASK1_PRIORITY 2
TaskHandle_t task1_handle;
StackType_t task1_stack[TASK1_STACK]; // 靜態任務的任務棧,以數組形式存儲
StaticTask_t task1_tcb; // 靜態任務的TCB結構體類型
void task1(void);
/* 任務2的配置 */
#define TASK2_STACK 128
#define TASK2_PRIORITY 3
TaskHandle_t task2_handle;
StackType_t task2_stack[TASK2_STACK]; // 靜態任務的任務棧,以數組形式存儲
StaticTask_t task2_tcb; // 靜態任務的TCB結構體類型
void task2(void);
/* 任務3的配置 */
#define TASK3_STACK 128
#define TASK3_PRIORITY 4
TaskHandle_t task3_handle;
StackType_t task3_stack[TASK3_STACK]; // 靜態任務的任務棧,以數組形式存儲
StaticTask_t task3_tcb; // 靜態任務的TCB結構體類型
void task3(void);
/* ======================= 靜態創建方式,需要手動指定2個特殊任務的資源=============================== */
/* 空閑任務的配置 */
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE]; // 靜態任務的任務棧,以數組形式存儲
StaticTask_t idle_task_tcb; // 靜態任務的TCB結構體類型
/* 軟件定時器任務的配置 */
StackType_t timer_task_stack[configTIMER_TASK_STACK_DEPTH]; // 靜態任務的任務棧,以數組形式存儲
StaticTask_t timer_task_tcb; // 靜態任務的TCB結構體類型
/* 分配空閑任務的資源 */
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer = &idle_task_tcb;
*ppxIdleTaskStackBuffer = idle_task_stack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/* 分配軟件定時器任務的資源 */
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize)
{
*ppxTimerTaskTCBBuffer = &timer_task_tcb;
*ppxTimerTaskStackBuffer = timer_task_stack;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
/**
* @description: 啟動FreeRTOS
* @return {*}
*/
void FreeRTOS_Start(void)
{
/* 1.創建一個啟動任務 */
start_task_handle = xTaskCreateStatic(
(TaskFunction_t)start_task, // 任務函數的地址
(char *)"start_task", // 任務名字符串
(uint32_t)START_TASK_STACK, // 任務棧大小,默認最小128,單位4字節
(void *)NULL, // 傳遞給任務的參數
(UBaseType_t)START_TASK_PRIORITY, // 任務的優先級
(StackType_t *)start_task_stack, // 我們創建的任務棧(數組存儲)的地址
(StaticTask_t *)&start_task_tcb // 我們創建的tcb的地址
);
/* 2.啟動調度器:會自動創建空閑任務和軟件定時器(如果開啟),
靜態創建的方式需要去實現2個分配資源的接口函數 */
vTaskStartScheduler();
}
int main(void)
{
// 初始化HAL庫函數必須要調用此函數
HAL_Init();
// 系統時鐘即AHB/APB時鐘配置
SystemClock_Config();
// 初始化LED
LedGpioInit();
KeyInit();
FreeRTOS_Start();
}
/**
* @description: 啟動任務:用來創建其他Task
* @param {void} *pvParameters
* @return {*}
*/
void start_task(void)
{
/* 進入臨界區:保護臨界區里的代碼不會被打斷 */
taskENTER_CRITICAL();
/* 使用靜態創建3個任務 */
task1_handle = xTaskCreateStatic(
(TaskFunction_t)task1,
(char *)"task1",
(configSTACK_DEPTH_TYPE)TASK1_STACK,
(void *)NULL,
(UBaseType_t)TASK1_PRIORITY,
(StackType_t *)task1_stack, // 我們創建的任務棧(數組存儲)的地址
(StaticTask_t *)&task1_tcb // 我們創建的tcb的地址
);
task2_handle = xTaskCreateStatic(
(TaskFunction_t)task2,
(char *)"task2",
(configSTACK_DEPTH_TYPE)TASK2_STACK,
(void *)NULL,
(UBaseType_t)TASK2_PRIORITY,
(StackType_t *)task2_stack, // 我們創建的任務棧(數組存儲)的地址
(StaticTask_t *)&task2_tcb // 我們創建的tcb的地址
);
task3_handle = xTaskCreateStatic(
(TaskFunction_t)task3,
(char *)"task3",
(configSTACK_DEPTH_TYPE)TASK3_STACK,
(void *)NULL,
(UBaseType_t)TASK3_PRIORITY,
(StackType_t *)task3_stack, // 我們創建的任務棧(數組存儲)的地址
(StaticTask_t *)&task3_tcb // 我們創建的tcb的地址
);
/* 啟動任務只需要執行一次即可,用完就刪除自己 */
vTaskDelete(NULL);
/* 退出臨界區 */
taskEXIT_CRITICAL();
}
void task1(void)
{
while(1)
{
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
vTaskDelay(500);
}
}
void task2(void)
{
while(1)
{
LED_TOGGLE(LED1_GPIO_PORT,LED1_GPIO_PIN);
vTaskDelay(500);
}
}
void task3(void)
{
while(1)
{
if(KeyScan() == 0)
{
if(task1_handle != NULL) vTaskDelete(task1_handle);
task1_handle = NULL;
}
vTaskDelay(500);
}
}
3、任務掛起與回復
3.1、任務掛起
/*傳入參數為任務句柄,若傳入NULL,則代表掛起當前任務*/
vTaskSuspend(task1_handle);
3.2 任務恢復
/* 任務恢復,傳入參數為任務句柄*/
vTaskResume(task1_handle);
3.3 掛起任務調度器
僅執行當前任務
vTaskSuspendAll();
3.4 恢復任務調度器
xTaskResumeAll();
3.5 打印任務狀態
/* 傳入參數為字符串 */
vTaskList(str);
3.6 中斷管理
/*執行此函數后,在中斷優先級閾值以下的中斷將被屏蔽*/
portDISABLE_INTERRUPTS();
/* 使能中斷 */
portENABLE_INTERRUPTS();
5、時間函數
/* 相對延時,每隔n個時間片執行一次代碼,不能保證代碼執行時間相同 */
vtaskDelay(n);
/* 絕對延時,代碼整體執行時間為n個時間片,保證代碼執行周期*/
xTaskDelayUntil();
6、任務之間通過隊列傳輸數據
#include "main.h"
#include "driver_led.h"
#include "driver_key.h"
#include "driver_uart.h"
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL庫函數必須要調用此函數
HAL_Init();
// 系統時鐘即AHB/APB時鐘配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任務句柄,用以保存不同任務的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函數作用:常規寫法,起始任務,用以創建其他任務
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任務函數的地址
(char *) "StartTask", //任務函數的名稱
(uint16_t) 128, //任務函數??臻g大小
(void *) NULL, //任務函數的參數
(UBaseType_t) 1, //任務函數的優先級
(TaskHandle_t*) &start_task_handle //任務函數的句柄
);
/* 啟用調度器,負責任務切換*/
vTaskStartScheduler();
}
/* 隊列句柄*/
QueueHandle_t handle1;
void StartTask(void)
{
/* 創建一個隊列 */
handle1 = xQueueCreate(1,sizeof(char *));
if(handle1 == NULL) UartSendData("task err");
/* 進入臨界保護區,保證在臨界區的代碼不會被打斷*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 2,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //刪除任務本身
/* 退出臨界保護區*/
taskEXIT_CRITICAL();
}
/*
* 函數作用:負責創建一個字符串,通過隊列發送出去
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task1(void)
{
char* str = "tehsjncncncncc";
while(1)
{
if(KeyScan() == KEY0)
{
/* 往隊列插入一個值,并設置阻塞等待*/
xQueueSend(handle1,&str,portMAX_DELAY);
UartSendData("Send Pass\r\n");
}
vTaskDelay(20);
}
}
/*
* 函數作用:接收數據任務
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task2(void)
{
char *buffer;
BaseType_t res;
while(1)
{
/* 接收隊列的任務,并進入阻塞等待*/
res = xQueueReceive(handle1,&buffer,portMAX_DELAY);
if(res == pdPASS)
{
UartSendData("buffer:\r\n");
UartSendData(buffer);
UartSendData("\r\n");
}
vTaskDelay(500);
}
}
7、二進制信號量釋放與接收
7.1 二進制信號量
#include "main.h"
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL庫函數必須要調用此函數
HAL_Init();
// 系統時鐘即AHB/APB時鐘配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任務句柄,用以保存不同任務的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函數作用:常規寫法,起始任務,用以創建其他任務
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任務函數的地址
(char *) "StartTask", //任務函數的名稱
(uint16_t) 128, //任務函數??臻g大小
(void *) NULL, //任務函數的參數
(UBaseType_t) 1, //任務函數的優先級
(TaskHandle_t*) &start_task_handle //任務函數的句柄
);
/* 啟用調度器,負責任務切換*/
vTaskStartScheduler();
}
/* 隊列句柄*/
QueueHandle_t handle1;
SemaphoreHandle_t semaphore_handle;
void StartTask(void)
{
/* 創建一個信號量 */
vSemaphoreCreateBinary(semaphore_handle);
if(semaphore_handle != NULL) UartSendData("Create success!\r\n");
/* 創建一個隊列 */
handle1 = xQueueCreate(1,sizeof(char *));
if(handle1 == NULL) UartSendData("task err");
/* 進入臨界保護區,保證在臨界區的代碼不會被打斷*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 2,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //刪除任務本身
/* 退出臨界保護區*/
taskEXIT_CRITICAL();
}
/*
* 函數作用:釋放信號量
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task1(void)
{
BaseType_t res;
while(1)
{
if(KeyScan() == KEY0)
{
/* 釋放信號量 */
res = xSemaphoreGive(semaphore_handle);
if (res == pdPASS) UartSendData("Send Pass\r\n");
}
vTaskDelay(20);
}
}
/*
* 函數作用:接收信號量
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task2(void)
{
BaseType_t res;
while(1)
{
/* 接收信號量是否釋放 */
res = xSemaphoreTake(semaphore_handle, portMAX_DELAY);
if(res == pdPASS)
{
UartSendData("Take success!\r\n");
UartSendData("\r\n");
}
vTaskDelay(500);
}
}
7.2 互斥二進制信號量
它會將阻塞高優先級的低優先級提升,從而保證高優先級不會被低優先級阻塞。
8、計數信號量釋放與接收
#include "main.h"
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL庫函數必須要調用此函數
HAL_Init();
// 系統時鐘即AHB/APB時鐘配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任務句柄,用以保存不同任務的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函數作用:常規寫法,起始任務,用以創建其他任務
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任務函數的地址
(char *) "StartTask", //任務函數的名稱
(uint16_t) 128, //任務函數??臻g大小
(void *) NULL, //任務函數的參數
(UBaseType_t) 1, //任務函數的優先級
(TaskHandle_t*) &start_task_handle //任務函數的句柄
);
/* 啟用調度器,負責任務切換*/
vTaskStartScheduler();
}
char str[100];
/* 隊列句柄*/
QueueHandle_t handle1;
void StartTask(void)
{
UBaseType_t Count = 0;
/* 創建一個信號量 */
handle1 = xSemaphoreCreateCounting(100, 0);
if(!(handle1 == NULL))
{
UartSendData("Create success!\r\n");
Count = uxSemaphoreGetCount(handle1);
sprintf(str, "the init count: %d", Count);
UartSendData(str);
}
/* 進入臨界保護區,保證在臨界區的代碼不會被打斷*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //刪除任務本身
/* 退出臨界保護區*/
taskEXIT_CRITICAL();
}
/*
* 函數作用:釋放信號量
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task1(void)
{
BaseType_t res;
while(1)
{
if(KeyScan() == KEY0)
{
/* 釋放信號量 */
res = xSemaphoreGive(handle1);
if (res == pdPASS) UartSendData("Send Pass\r\n");
}
vTaskDelay(20);
}
}
/*
* 函數作用:接收信號量
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task2(void)
{
char str[100];
UBaseType_t Count = 0;
BaseType_t res;
while(1)
{
/* 接收信號量是否釋放 */
res = xSemaphoreTake(handle1, portMAX_DELAY);
if(res == pdPASS)
{
UartSendData("Take success!\r\n");
UartSendData("\r\n");
UartSendData(str);
}
Count = uxSemaphoreGetCount(handle1);
sprintf(str, "the init count: %d\r\n", Count);
UartSendData(str);
vTaskDelay(1000);
}
}
9、隊列集
10、事件標志組
比信號量更靈活,每一個bit位都代表一個信號量。
#include "main.h"
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL庫函數必須要調用此函數
HAL_Init();
// 系統時鐘即AHB/APB時鐘配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任務句柄,用以保存不同任務的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函數作用:常規寫法,起始任務,用以創建其他任務
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任務函數的地址
(char *) "StartTask", //任務函數的名稱
(uint16_t) 128, //任務函數??臻g大小
(void *) NULL, //任務函數的參數
(UBaseType_t) 1, //任務函數的優先級
(TaskHandle_t*) &start_task_handle //任務函數的句柄
);
/* 啟用調度器,負責任務切換*/
vTaskStartScheduler();
}
char str[100];
EventGroupHandle_t event_handle;
void StartTask(void)
{
UBaseType_t Count = 0;
/* 創建一個信號量 */
event_handle = xEventGroupCreate();
if(!(event_handle == NULL))
{
UartSendData("Create success!\r\n");
}
/* 進入臨界保護區,保證在臨界區的代碼不會被打斷*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //刪除任務本身
/* 退出臨界保護區*/
taskEXIT_CRITICAL();
}
/*
* 函數作用:發送事件
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
#define EVENTBIT_0 (1 << 0)
#define EVENTBIT_1 (1 << 1)
void Task1(void)
{
EventBits_t res;
while(1)
{
xEventGroupSetBits(event_handle, 1<<3);
if(KeyScan() == KEY0)
{
/* 設置標志位*/
res = xEventGroupSetBits(event_handle, EVENTBIT_0);
sprintf(str,"event flag: %#x\r\n", res);
UartSendData(str);
res = xEventGroupSetBits(event_handle, EVENTBIT_1);
sprintf(str,"event flag: %#x\r\n", res);
UartSendData(str);
UartSendData("KEY0 PRESS!\r\n");
}
vTaskDelay(20);
}
}
/*
* 函數作用:接收事件
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task2(void)
{
EventBits_t res;
while(1)
{
/* 接收信號量是否釋放 */
res = xEventGroupWaitBits(
event_handle, // 事件句柄
((EVENTBIT_0 | EVENTBIT_1)), // 等待的標志位
pdTRUE, // 是否清楚標志位
pdTRUE, // 是否等待標志位
portMAX_DELAY // 等待事件
);
sprintf(str, "task2: %x\r\n", res);
UartSendData(str);
}
}
11 任務通知
11.1 任務通知模擬信號量
#include "main.h"
#include "portmacro.h"
#include "projdefs.h"
#include <stdint.h>
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL庫函數必須要調用此函數
HAL_Init();
// 系統時鐘即AHB/APB時鐘配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任務句柄,用以保存不同任務的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函數作用:常規寫法,起始任務,用以創建其他任務
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任務函數的地址
(char *) "StartTask", //任務函數的名稱
(uint16_t) 128, //任務函數??臻g大小
(void *) NULL, //任務函數的參數
(UBaseType_t) 1, //任務函數的優先級
(TaskHandle_t*) &start_task_handle //任務函數的句柄
);
/* 啟用調度器,負責任務切換*/
vTaskStartScheduler();
}
char str[100];
void StartTask(void)
{
/* 進入臨界保護區,保證在臨界區的代碼不會被打斷*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //刪除任務本身
/* 退出臨界保護區*/
taskEXIT_CRITICAL();
}
/*
* 函數作用:任務通知發送
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task1(void)
{
EventBits_t res;
while(1)
{
if(KeyScan() == KEY0)
{
/* 實際使取出task2的通知值,然后+1*/
xTaskNotifyGive(task2_handle);
UartSendData("KEY0 PRESS!\r\n");
}
vTaskDelay(200);
}
}
/*
* 函數作用:任務通知接收
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task2(void)
{
uint32_t res_notify;
while(1)
{
res_notify = ulTaskNotifyTake(
pdTRUE, //接收完通知后,是否對通知值處理,pdTRUE:置0;pdFALSE:-1
portMAX_DELAY //設置等待時間
);
sprintf(str, "task2 notify: %d\r\n", res_notify);
UartSendData(str);
}
}
11.2 任務通知模擬消息隊列(郵箱)
#include "main.h"
#include "portmacro.h"
#include "projdefs.h"
#include <stdint.h>
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL庫函數必須要調用此函數
HAL_Init();
// 系統時鐘即AHB/APB時鐘配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任務句柄,用以保存不同任務的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函數作用:常規寫法,起始任務,用以創建其他任務
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任務函數的地址
(char *) "StartTask", //任務函數的名稱
(uint16_t) 128, //任務函數棧空間大小
(void *) NULL, //任務函數的參數
(UBaseType_t) 1, //任務函數的優先級
(TaskHandle_t*) &start_task_handle //任務函數的句柄
);
/* 啟用調度器,負責任務切換*/
vTaskStartScheduler();
}
char str[100];
void StartTask(void)
{
/* 進入臨界保護區,保證在臨界區的代碼不會被打斷*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //刪除任務本身
/* 退出臨界保護區*/
taskEXIT_CRITICAL();
}
/*
* 函數作用:模擬消息隊列發送
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task1(void)
{
EventBits_t res;
while(1)
{
if(KeyScan() == KEY0)
{
xTaskNotify(task2_handle, // 要發送的任務句柄
100, // 要發送的數據
eSetValueWithOverwrite // 發送方式
);
UartSendData("KEY0 PRESS!\r\n");
}
vTaskDelay(200);
}
}
/*
* 函數作用:模擬消息隊列接收
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task2(void)
{
uint32_t res_notify;
while(1)
{
xTaskNotifyWait(
0x00000000, // 接收通知前是否清楚通知值,按位,全為0表示不不清楚
0xffffffff, // 接收通知后是否要清楚通知值,按位,全為f表示清楚
&res_notify, // 接受值存放地址
portMAX_DELAY // 等待事件
);
sprintf(str, "task2 notify: %d\r\n", res_notify);
UartSendData(str);
}
}
11.3 模擬事件標志組
#include "main.h"
#include "portmacro.h"
#include "projdefs.h"
#include <stdint.h>
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL庫函數必須要調用此函數
HAL_Init();
// 系統時鐘即AHB/APB時鐘配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任務句柄,用以保存不同任務的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函數作用:常規寫法,起始任務,用以創建其他任務
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任務函數的地址
(char *) "StartTask", //任務函數的名稱
(uint16_t) 128, //任務函數??臻g大小
(void *) NULL, //任務函數的參數
(UBaseType_t) 1, //任務函數的優先級
(TaskHandle_t*) &start_task_handle //任務函數的句柄
);
/* 啟用調度器,負責任務切換*/
vTaskStartScheduler();
}
char str[100];
void StartTask(void)
{
/* 進入臨界保護區,保證在臨界區的代碼不會被打斷*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //刪除任務本身
/* 退出臨界保護區*/
taskEXIT_CRITICAL();
}
/*
* 函數作用:模擬事件標志組發送
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task1(void)
{
EventBits_t res;
while(1)
{
if (KeyScan() == KEY0) {
xTaskNotify(task2_handle, // 要發送的任務句柄
1 << 8, // 要發送的數據位
eSetBits // 發送方式
);
UartSendData("KEY0 PRESS!\r\n");
}
vTaskDelay(200);
}
}
/*
* 函數作用:模擬事件標志組接收
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task2(void)
{
uint32_t res_notify;
while (1) {
xTaskNotifyWait(
0x00000000, // 接收通知前是否清楚通知值,按位,全為0表示不不清楚
0xffffffff, // 接收通知后是否要清楚通知值,按位,全為f表示清楚
&res_notify, // 接受值存放地址
portMAX_DELAY // 等待時間
);
sprintf(str, "task2 notify: %0x\r\n", res_notify);
UartSendData(str);
}
}
12、軟件定時器
#include "main.h"
#include <stdint.h>
void StartTask(void);
void Task1(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL庫函數必須要調用此函數
HAL_Init();
// 系統時鐘即AHB/APB時鐘配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
}
/* 任務句柄,用以保存不同任務的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
/*
* 函數作用:常規寫法,起始任務,用以創建其他任務
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任務函數的地址
(char *) "StartTask", //任務函數的名稱
(uint16_t) 128, //任務函數棧空間大小
(void *) NULL, //任務函數的參數
(UBaseType_t) 1, //任務函數的優先級
(TaskHandle_t*) &start_task_handle //任務函數的句柄
);
/* 啟用調度器,負責任務切換*/
vTaskStartScheduler();
}
char str[100];
void TimerCallBack_1(TimerHandle_t timer);
TimerHandle_t timer_handle_1;
/*
* 函數作用:開始任務回調函數
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void StartTask(void)
{
/* 創建軟件定時器,由軟件定時器任務(通過定義宏,由系統創建)控制*/
timer_handle_1 = xTimerCreate("time_1", // 創建名稱
500, // 定時器延遲時間
pdTRUE, // 是否重載(周期/一次)
(void *)1, // 定時器唯一ID
TimerCallBack_1 // 定時器回調函數
);
/* 進入臨界保護區,保證在臨界區的代碼不會被打斷*/
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t)Task1, (char *)"Task1", (uint16_t)128,
(void *)NULL, (UBaseType_t)3, (TaskHandle_t *)&task1_handle);
vTaskDelete(NULL); // 刪除任務本身
/* 退出臨界保護區*/
taskEXIT_CRITICAL();
}
/*
* 函數作用:開啟軟件定時器
* 輸入參數:無
* 返回值:無
* 作者:LSK
*/
void Task1(void)
{
EventBits_t res;
while (1) {
if (KeyScan() == KEY0) {
/* 開啟軟件定時器*/
xTimerStart(timer_handle_1, // 定時器句柄
portMAX_DELAY); // 等待時間
UartSendData(("timer start!\r\n"));
}
vTaskDelay(200);
}
}
/*
* 函數作用:定時器回調函數
* 輸入參數:定時器句柄
* 返回值:無
* 作者:LSK
*/
void TimerCallBack_1(TimerHandle_t timer)
{
if(timer == timer_handle_1)
{
UartSendData("Call back!\r\n");
LED_TOGGLE(LED0_GPIO_PORT, LED0_GPIO_PIN);
}
}

浙公網安備 33010602011771號