<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/LearnESP32" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>
說明
esp32是跑的freertos, 如果沒有學過操作系統的朋友把此節當做esp32的內部api使用就可以.
創建任務,每隔一段時間打印 Hello world

#include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" //任務函數 static void function(void *pvParameters) { while(1) { vTaskDelay(1000 / portTICK_PERIOD_MS);//延時約1S printf("Hello world!\r\n"); fflush(stdout);//手動調用刷新緩存,讓printf輸出數據 } } void app_main(void) { //創建任務 //第一個function是任務函數; 第二個"function"是給任務取個名字 //第三個2048是保存任務數據的棧區大小; 第四個傳遞給任務的參數寫的NULL //第五個任務的優先等級是10; 第六個記錄任務的變量寫的NULL xTaskCreate(function, "function", 2048, NULL, 10, NULL); }
各個細節說明
1.首先如果沒有學過rtos的把這個當做創建定時器就可以了
2.下面的是必須寫的
注:那個vTaskDelay函數有時候可以用別的替代,到時候遇到之后再說.
寫了下面的程序以后,就會不停的執行while(1)里面的程序.

3.可以修改延時時間

4.可以再創建個任務

#include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" //任務函數 static void function(void *pvParameters) { while(1) { vTaskDelay(500 / portTICK_PERIOD_MS);//延時約500ms printf("Hello world!\r\n"); fflush(stdout);//手動調用刷新緩存,讓printf輸出數據 } } //任務函數 static void function_1(void *pvParameters) { while(1) { vTaskDelay(500 / portTICK_PERIOD_MS);//延時約500ms printf("1111111111!\r\n"); fflush(stdout);//手動調用刷新緩存,讓printf輸出數據 } } void app_main(void) { //創建任務 //第一個function是任務函數; 第二個"function"是給任務取個名字 //第三個2048是保存任務數據的棧區大小; 第四個傳遞給任務的參數寫的NULL //第五個任務的優先等級是10; 第六個記錄任務的變量寫的NULL xTaskCreate(function, "function", 2048, NULL, 10, NULL); xTaskCreate(function_1, "function_1", 2048, NULL, 11, NULL); }
5.可以看到兩個字符串幾乎是每隔500ms同時打印

6.關於棧區大小
任務在運行的時候,每個任務是來回切換運行的,操作系統在切換別的任務運行的時候,會把當前任務運行的寄存器,變量的值存儲到內存(ram)里面.
當再次回到這個任務運行的時候,從內存把寄存器,變量的值讀取出來,這樣子的話就可以接着上次運行了.
保存數據大小我設置的是2048.

7.獲取這個任務自啟動以后剩余的最小棧區空間
uxTaskGetStackHighWaterMark( NULL );
中文是亂碼....不用理會,咱可以看出剩下的棧空間是568

8.難道使用了 2048-568 = 1480 ????
一個啥也沒有的任務不可能使用這么多的,其實返回的是這個任務運行的時候使用的最大空間.
但是網絡是都是說這個函數是剩下的棧空間呢? 如何解釋?
其實是棧的生長方向的問題!
首先呢保存數據就是使用的數組保存的,數組有首地址和尾地址.
假設存儲數據的時候是從首地址開始存儲的,假設存儲了568個數據,那么數據最大存儲在568這個地址
那么就剩余1480個空間沒有使用.那么返回的時候返回剩下的就是1480;
如果存儲數據的時候是從數組的尾地址開始存儲的,假設存儲568個數據,其實數據是存儲到 2047,2046,...,1479,1480 這些地址上
最終存儲的地址是1480,但是呢從數組的首地址開始計算的話就會認為存儲了1480個數據
那么便會計算出剩余568,正好和上面的相反.所以才返回568.
9.大家伙可以把這個地方改為 566 和 569測試
大家伙會發現設置為566的時候,任務啟動不起來,程序總是在重啟. 設置569是可以的.
所以呢函數 uxTaskGetStackHighWaterMark( NULL ); 在這個里面其實是獲取的使用的最大空間

10.一般呢把空間設置為實際使用空間的1.5倍或者2倍就可以 568*2=1136

停止(掛起)任務 vTaskSuspend(任務句柄)
function1運行約3秒后,停止function任務的運行

#include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" //任務句柄,用來對任務做其它操作 TaskHandle_t TaskHandle_t_function; //任務函數 static void function(void *pvParameters) { while(1) { vTaskDelay(500 / portTICK_PERIOD_MS);//延時約500ms printf("222222!\r\n"); fflush(stdout);//手動調用刷新緩存,讓printf輸出數據 } } //任務函數 static void function_1(void *pvParameters) {while(1) { vTaskDelay(3000 / portTICK_PERIOD_MS);//延時約3000ms vTaskSuspend(TaskHandle_t_function);//停止function任務運行(掛起function任務) } } void app_main(void) { //第一個function是任務函數; 第二個"function"是給任務取個名字 //第三個2048是保存任務數據的棧區大小; 第四個傳遞給任務的參數寫的NULL //第五個任務的優先等級是10; 第六個記錄任務的變量寫的NULL xTaskCreate(function, "function", 1136, NULL, 10, &TaskHandle_t_function); xTaskCreate(function_1, "function_1", 2048, NULL, 11, NULL); }

啟動被停止(掛起)的任務 vTaskResume(任務句柄)


刪除任務 vTaskDelete()

