ESP32 Arduino:创建FreeRTOS任务-esp文件

本ESP32 Arduino教程的代码在ESP32进行了测试。

简 介

本文主要介绍如何使用FreeRTOS函数创建任务。因为涉及到一些比较复杂的概念,我们将从一个非常简单的示例开始。在这个例子中,我们会先创建两个打印“Hello World”消息的任务,然后将它们删除。

有关本教程将用到的绝大多数功能,均可参阅这里(https://github.com/espressif/arduino-esp32/blob/3c071e1d899707bc4d63aed63de4772f62d5be53/tools/sdk/include/freertos/freertos/task.h) 的.h文件。有关FreeTROS和任务的介绍请参阅此前的这篇帖子:ESP32 Arduino:使用FreeRTOS函数(http://mc.dfrobot.com.cn/thread-280487-1-1.html)。

setup函数和循环代码

在setup函数中,首先要打开一个串行连接,用于输出测试程序的运行结果。这是常规的Arduino功能。

Serial.begin(112500);

delay(1000);

然后,调用xTaskCreate函数(http://esp32.info/docs/esp_idf/html/dd/d3c/group__xTaskCreate.html)以创建任务。该函数的参数如下所述[1]:

TaskCode:我们需要把一个函数指针(该函数负责任务的实现)传递给这个参数。我们将创建两个函数(TaskOne和TaskTwo),它们的定义在后面的代码中,我们将把这两个函数传递给这个参数。

TaskName:任务的名称,以字符串表示。我们要创建的两个任务名称分别为“TaskOne”和“TaskTwo”。

StackDepth:任务堆栈大小,以字节数表示。尽管可以进行一些计算,但是并没有一种简单的方式能够确定任务的大小[2]。在简单的示例中,我们通常会使用一个足够大的数值。

Update:在最初的帖子里,提到StackDepth是以字(word)数表示的,FreeRTOS xTaskCreate文档(https://www.freertos.org/a00125.html)也是如此。但是,IDF版的具体实现有所不同,堆栈深度实际上是以字节数表示的,如IDF文档所述:https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/freertos-smp.html#tasks-and-task-creation 。我们在IDF的FreeRTOS task.h文件(https://github.com/espressif/esp-idf/blob/master/components/freertos/include/freertos/task.h#L375)里也能对此予以验证。

Parameter:指针,指向任务函数所接收的参数。其类型必须为(void *) [2]。在本教程中,为简单起见,我们将不会使用这个参数(参数值为NULL)。

Priority:任务的优先级。我们将创建两个具有相同优先级的任务。

TaskHandle:返回一个句柄,用于以后进行函数调用(比如要删除某个任务或者修改其优先级)时对任务的引用[2]。同样地,在这个简单示例中,我们将不使用这个参数(参数值为NULL)。

该函数会返回pdPass(成功时)或错误代码[1] (http://esp32.info/docs/esp_idf/html/db/d67/projdefs_8h.html)。我们假设任务创建时不会有任何问题,所以代码中不会进行任何错误校验。当然,在实际的应用场景中,应该确认任务是否创建成功。

完整的setup函数如下所示,其中包括了创建两个不同任务的函数调用。


[/font][/align][font=微软雅黑]void setup() {



Serial.begin(112500);

delay(1000);



xTaskCreate(

taskOne, /* Task function. */

"TaskOne", /* String with name of task. */

10000, /* Stack size in bytes. */

NULL, /* Parameter passed as input of the task */

1, /* Priority of the task. */

NULL); /* Task handle. */



xTaskCreate(

taskTwo, /* Task function. */

"TaskTwo", /* String with name of task. */

10000, /* Stack size in bytes. */

NULL, /* Parameter passed as input of the task */

1, /* Priority of the task. */

NULL); /* Task handle. */



}

因为所创建的两个任务已经实现了所有功能,所以主循环什么也不用做。我们在主循环中只放了一个延时。


void loop() {

delay(1000);

}

任务函数

现在,我们唯一需要做的就是指定任务函数。不要忘了,我们要创建两个任务,分别由函数TaskOne和TaskTwo实现。

请注意,这些任务都将使用正则函数实现,因此它们需要遵循预先定义的函数原型[3]。它们必须返回空(void),而且必须接收(void *)类型的输入参数[3],如下例所示。

 
void taskOne( void * parameter )

有一点非常重要,那就是这个函数不应该返回任何数值。因此,它们不能包含return语句或者执行到代码结尾[3]。相反,应该显式地将其删除[3]。

要在某个任务的代码内部将其自身删除,我们只需要调用它的TaskDelete函数即可。该函数接收的输入参数是要删除的任务句柄[4](就是前面提到本教程不使用的xTaskCreate函数的参数)。尽管如此,如果我们将输入参数值设为NULL,那么主调任务仍然能被删除[4],这正是我们想要的效果(我们会从任务自身代码内部进行调用)。

 
vTaskDelete( NULL );

除了这几点不同之外,这两个函数的实现非常简单。简而言之,我们将使用一个简单的循环,让每个任务打印一条“Hello World”消息,循环结束后再打印一条表示任务已结束的消息。

本教程的完整代码如下所示,其中包括两个任务的实现代码。


[/font][/align][font=微软雅黑]void setup() {



Serial.begin(112500);

delay(1000);



xTaskCreate(

taskOne, /* Task function. */

"TaskOne", /* String with name of task. */

10000, /* Stack size in bytes. */

NULL, /* Parameter passed as input of the task */

1, /* Priority of the task. */

NULL); /* Task handle. */



xTaskCreate(

taskTwo, /* Task function. */

"TaskTwo", /* String with name of task. */

10000, /* Stack size in bytes. */

NULL, /* Parameter passed as input of the task */

1, /* Priority of the task. */

NULL); /* Task handle. */



}



void loop() {

delay(1000);

}



void taskOne( void * parameter )

{



for( int i = 0;i<10;i++ ){



Serial.println("Hello from task 1");

delay(1000);

}



Serial.println("Ending task 1");

vTaskDelete( NULL );



}



void taskTwo( void * parameter)

{



for( int i = 0;i<10;i++ ){



Serial.println("Hello from task 2");

delay(1000);

}

Serial.println("Ending task 2");

vTaskDelete( NULL );



}

运行代码

使用Arduino IDE对代码进行编译并上传到ESP32开发板,即可运行代码。运行结果如图1所示,串行控制台会打印出两条“Hello World”消息。最后,两条表示任务结束的消息也会打印到控制台上。


ESP32 Arduino:创建FreeRTOS任务


图1 - 程序运行结果。

请注意,两个任务是并行运行的,所以两个任务打印的消息是混在一起的。每个任务的执行时间由RTOS调度器决定。

注:本文作者是Nuno Santos,他是一位和蔼可亲的电子和计算机工程师,住在葡萄牙里斯本 (Lisbon)。

他写了很多有关ESP32、ESP8266的有用的教程和项目。

查看更多ESP32/ESP8266教程和项目,请点击:DF创客社区 - 分享创造的喜悦

推荐阅读

    excel怎么用乘法函数

    excel怎么用乘法函数,乘法,函数,哪个,excel乘法函数怎么用?1、首先用鼠标选中要计算的单元格。2、然后选中单元格后点击左上方工具栏的fx公

    鼠标不能拖动文件了

    鼠标不能拖动文件了,鼠标,拖动,本文目录鼠标不能拖动文件了电脑鼠标无法拖动软件图标了,怎么办鼠标不能滚动怎么调整电脑鼠标不能进行任何

    excel中乘法函数是什么?

    excel中乘法函数是什么?,乘法,函数,什么,打开表格,在C1单元格中输入“=A1*B1”乘法公式。以此类推到多个单元。1、A1*B1=C1的Excel乘法公式

    标准差excel用什么函数?

    标准差excel用什么函数?,函数,标准,什么,在数据单元格的下方输入l标准差公式函数公式“=STDEVPA(C2:C6)”。按下回车,求出标准公差值。详细

    如何创建宽带连接(图形)

    如何创建宽带连接(图形),,很多时候,由于计算机的使用不当,计算机网络连接遭到破坏。此时,我们需要自己创建宽带连接。下面我们将教你如何创建宽