Hello world
程序是所有初学者学习编程或进行设备调试最基本、最简单的程序,而对于刚刚接触 ESP32 芯片的初学者而言,Hello world
程序可以帮助我们更好的理解整个系统,还可以用来确定该语言的编译器、程序开发环境,以及运行环境是否已经安装妥当。
下面本文将会阐述 ESP32
上, Hello world
程序的实现框架和过程。
学习本章之前,请确保已经按照教程安装好相应的 IDF 和 GCC 编译器环境.
参考:https://esp-idf.readthedocs.io/zh_CN/latest/get-started/index.html
ESP32
所使用的框架为 ESP-IDF
(Espressif IoT Development Framework), ESP-IDF
可以看作是不同功能组件(component)的集成,每一个组件(component)一般只实现一类功能。
ESP-IDF
让这些组件易于配置使用,用户可以自由选择这些组件加入到自己的项目中。
如 fatfs
组件只是实现 FAT 文件系统; driver
组件中包含了 ESP32
所拥有的所有外设驱动。
这些组件的参数通过 make menuconfig
进行修改配置。
在使用 ESP32
开发复杂程序时,也可以把某一类功能作为 component 放在 main 目录下。
ESP-IDF 会自动编译此 component 并链接到最终的程序中。
对于 Hello world
程序,我们可以看到目录结构如下:
- hello_world/
- Makefile
- main/ - hello_world_main.c
- component.mk
- README.md
- sdkconfig(编译生成或者自己添加)
- build/(编译生成)
Hello world 这个项目主要包含如下元素:
项目 Makefile
会设置 PROJECT_NAME
变量,编译生成的用户 BIN
文件名即为此文件名;然后还会包含 ESP_IDF
的核心 Makefile : $(IDF_PATH)/make/project.mk,注意的是只有包含此 Makefile
文件才会最终链接到 ESP-IDF
上去,否则会无法使用所有的 components
。一般简单的 demo 只需要包含这两项即可,但也可以另外设置本项目需要编译和配置的 make
功能。
main
目录包含了程序的源代码以及一个 component.mk
文件,其中 component.mk
会把用户项目编译集成到 ESP-IDF
中,里面可以为空,也可以只包含一些变量定义控制 component
的编译过程。如果没有 component.mk
文件, ESP-IDF 不会编译此目录,在运行时会报出无法找到 app_main
的错误。
sdkconfig
文件会在编译后自动生成,里面主要包含用户的项目配置信息,这个文件可以通过使用 make menuconfig
进行更改, 配置信息会对所有的 component
生效(包括 ESP-IDF
),一般用户可以创建 sdkconfig.defaults
文件来保存本项目必须的配置项,这样可以防止其他使用者胡乱修改配置导致编译出错。
build
目录在编译时生成,是放置编译输出的文件夹,里面包含每个 component
的中间结果以及最后的二进制执行文件。
#include
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
以上为
Hello world
程序所需要的头文件,其中包含了一个标准头文件,两个FreeRTOS
头文件和两个乐鑫头文件(以esp_
开头)。
void app_main()
{
app_main
为整个程序入口,系统会自动查找app_main
函数,并从此函数开始执行(类似于 C 语言中的main
函数)。在此函数中,可以初始化一些应用,比如创建其他task
,app_main
函数不能返回,否则会删除 main task 导致 crash。
/* Print chip information */
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
printf("This is ESP32 chip with %d CPU cores, WiFi%s%s, ",
chip_info.cores,
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
printf("silicon revision %d, ", chip_info.revision);
printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
以 esp 开头的函数均为乐鑫提供的接口,上述代码主要打印芯片信息,
esp_chip_info()
函数在esp_system.h
中定义,作用是获取芯片的信息,以esp_chip_info_t
返回,其中包含CPU
核数,芯片版本号等信息,spi_flash_get_chip_size()
函数在esp_spi_flash.h
中定义,作用是获取flash
的大小。
for (int i = 10; i >= 0; i--) {
printf("Restarting in %d seconds...\n", i);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
printf("Restarting now.\n");
fflush(stdout);
esp_restart();
}
循环 10 次,每隔 1s 打印一次消息,循环结束后,打印并立即输出所有缓存数据,然后调用 esp_restart() 重启,其中
esp_restart()
在esp_system.h
中定义,对芯片进行软重启。
代码运行结果如下:
从以上代码可以看出, Hello world
程序与其他嵌入式入门程序差别不大,在使用中只需注意相关乐鑫 API 即可。
从构架上来看,esp-idf
框架依靠其独特的组件 (component)特点,缩减了各个组件之间的耦合性,使得客户可以轻松的集成 esp-idf 中的所有功能,并可以很方便开发自己的代码。