ESP模塊因其Wi-Fi功能(如ESP8266、ESP-12E等)而廣受歡迎。這些都是具有Wi-Fi功能的強(qiáng)大微控制器模塊。還有一個(gè)ESP模塊,它比以前的ESP模塊更強(qiáng)大,更通用 - 其名稱為ESP32。它具有藍(lán)牙和Wi-Fi連接,并在許多物聯(lián)網(wǎng)項(xiàng)目中使用了ESP32。但是很少有人知道ESP32是雙核微控制器。
ESP32具有兩個(gè)32位TensilicaXtensa LX6微處理器,這使其成為功能強(qiáng)大的雙核(core0和core1)微控制器。有單核和雙核兩種版本。但是雙核版本更受歡迎,因?yàn)樗鼈冎g沒(méi)有明顯的價(jià)格差異。
可以使用Arduino IDE、Espressif IDF、Lua RTOS等對(duì)ESP32進(jìn)行編程。使用Arduino IDE進(jìn)行編程時(shí),由于Core0已編程用于RF通信,因此代碼僅在Core1上運(yùn)行。但是在本篇文章中,我們將展示如何使用ESP32的兩個(gè)內(nèi)核同時(shí)執(zhí)行兩項(xiàng)操作。在這里,第一個(gè)任務(wù)是使板載LED閃爍,第二個(gè)任務(wù)是從DHT11傳感器獲取溫度數(shù)據(jù)。
首先讓我們看看多核處理器比單核的優(yōu)勢(shì)。
多核處理器的優(yōu)勢(shì)
1.當(dāng)有兩個(gè)以上的進(jìn)程要同時(shí)工作時(shí),多核處理器很有用。
2.由于工作分布在不同的內(nèi)核之間,因此速度提高了,并且可以同時(shí)完成多個(gè)過(guò)程。
3.可以降低功耗,因?yàn)楫?dāng)任意內(nèi)核處于空閑模式時(shí),它可以用來(lái)關(guān)閉當(dāng)時(shí)不使用的外圍設(shè)備。
4.與單核處理器相比,雙核處理器在不同線程之間切換的頻率更低,因?yàn)樗鼈兛梢砸淮翁幚韮蓚€(gè),而不是一次處理一個(gè)線程。
ESP32和FreeRTOS
ESP32開(kāi)發(fā)板已經(jīng)安裝了FreeRTOS固件。 FreeRTOS是開(kāi)源的實(shí)時(shí)操作系統(tǒng),在多任務(wù)處理中非常有用。 RTOS有助于管理資源并最大程度地提高系統(tǒng)性能。 FreeRTOS具有許多用于不同目的的API函數(shù),使用這些API,我們可以創(chuàng)建任務(wù)并使它們運(yùn)行在不同的內(nèi)核上。
FreeRTOS API的完整文檔可以在這里找到。我們將嘗試在代碼中使用一些API來(lái)構(gòu)建在兩個(gè)內(nèi)核上運(yùn)行的多任務(wù)應(yīng)用程序。
查找ESP32內(nèi)核ID
在這里,我們將使用Arduino IDE將代碼上傳到ESP32。要知道運(yùn)行代碼的Core ID,有一個(gè)API函數(shù)
xPortGetCoreID()
可以從void setup()和void loop()函數(shù)中調(diào)用此函數(shù),以了解運(yùn)行這些函數(shù)的內(nèi)核ID。
您可以通過(guò)上傳以下草圖來(lái)測(cè)試此API:
void setup() {
Serial.begin(115200);
Serial.print("setup() function running on core: ");
Serial.println(xPortGetCoreID());
}
void loop() {
Serial.print("loop() function running on core: ");
Serial.println(xPortGetCoreID());
}
上傳完上述草圖后,打開(kāi)串口監(jiān)視器,您會(huì)發(fā)現(xiàn)這兩個(gè)函數(shù)都在core1上運(yùn)行,如下所示。
從以上觀察結(jié)果可以得出結(jié)論,默認(rèn)的Arduino草圖始終在core1上運(yùn)行。
ESP32雙核編程
Arduino IDE支持在ESP32運(yùn)行FreeRTOS,而FreeRTOS API允許我們創(chuàng)建可以在兩個(gè)內(nèi)核上獨(dú)立運(yùn)行的任務(wù)。任務(wù)是一段在開(kāi)發(fā)板上執(zhí)行某些操作的代碼,例如LED閃爍、發(fā)送溫度等。
以下函數(shù)用于創(chuàng)建可以在兩個(gè)內(nèi)核上運(yùn)行的任務(wù)。在此函數(shù)中,我們必須提供一些參數(shù),例如優(yōu)先級(jí)、內(nèi)核ID等。
現(xiàn)在,按照以下步驟創(chuàng)建任務(wù)和任務(wù)函數(shù)。
1.首先,在void setup函數(shù)中創(chuàng)建任務(wù)。在這里,我們將創(chuàng)建兩個(gè)任務(wù),一個(gè)任務(wù)是每0.5秒閃爍一次LED,另一任務(wù)是每2秒獲得溫度讀數(shù)。
xTaskCreatePinnedToCore()函數(shù)使用7個(gè)參數(shù):
● 實(shí)現(xiàn)任務(wù)的函數(shù)名稱(task1)
● 任務(wù)的任何名稱(“ task1”等)
● 分配給任務(wù)的堆棧大小,以字為單位
● 任務(wù)輸入?yún)?shù)(可以為NULL)
● 任務(wù)的優(yōu)先級(jí)(0是最低優(yōu)先級(jí))
● 任務(wù)句柄(可以為NULL)
● 任務(wù)將運(yùn)行的內(nèi)核ID(0或1)
現(xiàn)在,通過(guò)在xTaskCreatePinnedToCore()函數(shù)中提供所有參數(shù)來(lái)創(chuàng)建Task1,以使指示燈閃爍。
xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, NULL,0);
同樣,為任務(wù)2創(chuàng)建Task2,并在第7個(gè)參數(shù)中將內(nèi)核ID設(shè)置為1。
xTaskCreatePinnedToCore(Task2code, "Task2", 10000, NULL, 1, NULL,1);
您可以根據(jù)任務(wù)的復(fù)雜性更改優(yōu)先級(jí)和堆棧大小。
2.現(xiàn)在,我們將實(shí)現(xiàn)Task1code和Task2code函數(shù)。這些函數(shù)包含所需任務(wù)的代碼。在本例中,第一個(gè)任務(wù)將使LED閃爍,另一個(gè)任務(wù)將獲取溫度。因此,在void setup函數(shù)之外,為每個(gè)任務(wù)創(chuàng)建兩個(gè)單獨(dú)的函數(shù)。
Task1code函數(shù)實(shí)現(xiàn)了0.5秒后板上LED閃爍,如下所示:
Void Task1code( void * parameter) {
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for(;;) {//infinite loop
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
??delay(500);
}
}
同樣,實(shí)現(xiàn)Task2code函數(shù)以獲取溫度。
void Task2code( void * pvParameters ){
Serial.print("Task2 running on core ");
Serial.println(xPortGetCoreID());
for(;;){
float t = dht.readTemperature();
Serial.print("Temperature: ");
Serial.print(t);
delay(2000);
}
}
3.此處的void loop函數(shù)將保持為空。 我們已經(jīng)知道loop和setup函數(shù)在core1上運(yùn)行,因此您也可以在void loop函數(shù)中實(shí)現(xiàn)core1任務(wù)。
現(xiàn)在代碼部分已經(jīng)結(jié)束,因此只需在“Tool”菜單中選擇ESP32板,即可使用Arduino IDE上傳代碼。 確保已將DHT11傳感器連接到ESP32的D13引腳。
現(xiàn)在,可以在串口監(jiān)視器上監(jiān)視結(jié)果,如下所示:
可以通過(guò)使用ESP32的雙核同時(shí)運(yùn)行多個(gè)任務(wù)來(lái)構(gòu)建諸如實(shí)時(shí)系統(tǒng)之類的復(fù)雜應(yīng)用程序。
編輯:hfy
-
微控制器
+關(guān)注
關(guān)注
48文章
7542瀏覽量
151316
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論