【立创·实战派ESP32-S3】文档教程
第 3 章 开发流程详解
我们通过 IDF 自带的 Hello World 例程来熟悉一下 VSCode 开发 ESP32 的步骤流程,本章节小白必看,这里会讲解如何编写代码、编译代码、下载代码。主要是介绍在 VSCode 界面中,ESP-IDF 插件中的各个功能图标的作用与使用方法。
3.1 准备 hello_world 例程
在硬盘上新建一个文件夹,用来做实验,要求路径,纯英文字符,且不能有空格。例如,我是在 D 盘新建了一个名称为 esp32s3 的文件夹,所以我的实验文件夹路径是 D:\esp32s3。
IDF 文件夹里面提供了很多例程,它的例程文件位于 IDF 文件夹的 examples 文件夹中。
复制官方 hello_world 例程文件夹到我们的实验文件夹。官方 hello_world 例程文件夹位于 IDF 文件夹的 examples\get-started\,复制到我的实验文件夹以后的路径是 D:\esp32s3\hello_world。
有两种方法打开工程。
第一种,在 hello_world 文件夹上先单击左键选中,再单击右键,再弹出的菜单中选择“通过 Code 打开”,如下图所示。
注意:1、一定要先单击左键选中文件夹,然后再单击右键,否则会打开此文件夹上层的文件夹。 2、如果你的菜单中没有“通过 Code 打开”命令,是因为你在安装 VSCode 的时候没有勾选相关选项,具体看 第 2 章 2.1 小节安装 VSCode,重装一遍 VSCode 即可。
第二种,打开 VSCode 软件,使用菜单“文件”->“打开文件夹”,选择 D:\esp32c3\hello_world 文件夹打开它,如下图所示。
打开工程后,我们在 VSCode 左侧的项目面板中,点击 main 前面的“>”符号,展开 main 里面的文件,如下图所示:
我们点击 hello_world_main.c 文件,这个文件就在右侧打开了。这个文件里面的程序,就是 ESP32 要运行的代码,其中,app_main 是主函数。
现在我们先了解一下工程结构。
在这个 hello_world 工程中,sdkconfig.ci 文件和 pytest_hello_world.py 文件是 pytest 测试框架需要用的,在这个工程里面,我们并不需要,这两个文件并不会影响程序的编译和运行,把这两个文件删除。
关于 pytest 的使用,可以看这个链接的介绍,本教程不涉及这方面教学内容,感兴趣的可以学。 ESP-IDF pytest 指南 - ESP32-S3 - — ESP-IDF 编程指南 latest 文档
README.md 文件是对本工程的简单说明,也不参与程序的编译和运行。
剩下的几个文件,就是一个工程的最小结构了。main 目录,包含一个 main.c 文件,以及一个 CMakeLists.txt 文件,在 main 同级目录下,也包含一个 CMakeLists.txt 文件。这两个 CMakeLists.txt 文件在工程中起到的作用不一样。
我们点击一级目录下的 CMakeLists.txt 文件,也就是和 main 同级目录下的 CMakeLists.txt 文件,右侧可以看到里面的内容,如下代码所示。
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hello_world)
2
3
4
5
6
文件中#符号后面是注释,不参与编译。
第 3 行,指定 CMake 最小版本。ESP32 程序使用 CMake 编译,CMake 是一款跨平台的编译工具。关于 CMake 的详解介绍和使用方法,大家可以去网络上学习。因为 IDF 基本上已经做好了 CMake 相关配置,这里不需要你太深入的了解 CMake,跟着我们的教程,知道改哪里,为什么要改,就足够用了。
第 5 行,用来包含 IDF 的路径。
第 6 行的 project(hello_wrold),括号里面的名称,我们叫做工程名称,一般和工程文件夹名称一致,也可以不一样。这里面的名称,决定了编译后的 bin 文件的名称,比如现在编译后的 bin 文件名称就是 hello_world.bin 文件,如果你改成了 project(xxx),编译后的名称就是 xxx.bin。
我们点击 main 目录下的 CMakeList.txt 文件,右侧可以看到里面的内容,如下代码所示。
idf_component_register(SRCS "hello_world_main.c"
INCLUDE_DIRS "")
2
这个里面是用来添加源文件路径的,本工程里面只有一个 c 文件,所以只有一个 hello_world_main.c。如果工程中需要再添加一个 c 文件,就可以在这里添加新的 c 文件的名称。一般情况下,当你在工程中新建一个 c 文件后,这里会自动把你新建的 c 文件添加进入,如果没有自动添加进入,手动添加即可,这里我们先了解一下就可以,我们在后面学习其它例程的时候会用到。
本工程的现象是在串口终端输出 hello world,然后经过 10 秒钟后重启,如此往复。程序不用做修改,直接编译下载就可以。接下来看看编译下载的配置流程。
3.2 编译和下载
在 VSCode 左下角,有一些选项需要配置,如下图所示。
第 1 个图标,可以配置需要使用的 IDF 版本号,点击图标,在 VSCode 软件中间最上方会出现可选的 IDF 版本号,如下图所示。如果你只安装了一个版本,就不用配置了。
第 2 个配置图标是串口号的选择。点击图标,在 VSCode 软件中间最上方会出现可选的串口号。在选择串口号之前,必须要先把开发板插到电脑上。点击后在 VSCode 软件的中间最上方就出现可选的串口号,如下图所示,选择带有 ESP32 字样的就可以,如下所示,我们点击选择 COM19。在点击的时候,单片机会重启一次。
第 3 个配置图标是目标芯片的选择。点击图标,在 VSCode 软件中间最上方,首先会出现工程路径,点击选择,然后就会出现可选的芯片型号,我们选择 esp32s3。
点击 esp32s3 之后,又会弹出下载方式的选择,这里出现三种方式,第一种是使用 ESP-PROG,第二种是使用内置 USB-JTAG,第三种是选择 USB 转串口,这里我们选择第三种:via ESP USB Bridge。
上图是 5.1.4 版本出现的名称,如果是 5.2.2 版本,第三种的名称是 via ESP-PROG-2,如下图所示,这个也是通过 USB 转串口下载,看最后面括号里的配置文件名称就可以知道。(board/eps32s3-bridge.cfg)
选择好目标芯片和下载方式后,需要等 VSCode 软件右下角的进度条状态完成之后再进行下一步。
这时候,我们看到在工程中出现了.vscode和build文件夹,以及一个sdfconfig文件。如下图所示。.vscode 放配置文件,build 放编译过程中形成的文件,编译完以后,整个工程中,build 文件夹占的空间最大。
.vscode 文件夹里面有个 settings.json 配置文件,点击打开这个配置文件,可以在里面找到刚才的配置。
"idf.portWin": "COM19"
表示是选择的串口号;
"idf.adapterTargetName": "esp32s3"
表示选择的目标芯片是 esp32s3;
"idf.openOcdConfigs": ["board/esp32s3-bridge.cfg"]
表示使用 USB 转串口下载程序。
{
......
"idf.portWin": "COM19",
"idf.adapterTargetName": "esp32s3",
......
"idf.openOcdConfigs": [
"board/esp32s3-bridge.cfg"
]
......
}
2
3
4
5
6
7
8
9
10
刚才生成的 sdfconfig 文件,是 menuconfig 的默认配置,可以点击查看里面的内容。
第 4 个文件夹图标是工程文件夹路径,默认会自动配置好,不用修改,把鼠标放上去就可以看到当前工程路径。
第 5 个齿轮图标是 menuconfig 图标,点击图标会打开 menuconfig,如下图所示。配置 FLASH 芯片大小为 16MB 后(开发板上使用的 FLASH 大小是 16MB),点击“保存”图标保存,最后点击“X”退出。
menuconfig 配置完成后,会生成一个sdkconfig.old文件,这个其实是刚才设置目标芯片生成的 sdkconfig 文件,最新的配置,已经更新到了现在的sdkconfig文件里面。以后每次修改 menuconfig,都会更新 sdfconfig 文件,同时把之前的配置更新到 sdkconfig.old,起到备份作用。
第 6 个垃圾桶形象图标,用来删除编译过程中形成的文件,也就是删除 build 文件夹。这里我们还没有编译,用不着处理。
第 7 个扳手图标是编译按钮,点击这个按钮,就可以开始编译。这里先不要点。
第 8 个五角星图标是下载方式的选择,我们选择 UART。
第 9 个闪电图标是下载按钮,点击这个按钮,可以下载编译好的程序到 ESP32 开发板。这里还没有编译,所以不用点。
第 10 个显示器图标是终端观察窗口,下载完程序以后,我们可以点击这个按钮,观察单片机的运行状态,这个其实就是一个串口终端,程序运行过程中,会使用串口发送一些信息,在这个终端就可以看到。
第 11 个三角形图标是调试按钮,我们暂时用不到。
第 12 个火焰图标是编译、下载、终端的综合按钮,相当于是依次点击了上面讲的扳手、闪电、显示器按钮,我们也称这个按钮为“一键三联”按钮。点击一下,会按照顺序完成编译、下载、打开终端。
现在,我们点击这个“一键三联”按钮,程序就开始编译了。第一次编译,需要的时间比较长,之后如果稍微修改一下程序再编译,编译时间就没有第一次那么长了。在编译的过程中,会在终端窗口看到编译过程的信息。等到程序下载完毕,会自动打开终端,我们会在终端中看到如下信息:
Hello world!
This is esp32s3 chip with 2 CPU core(s), WiFi/BLE, silicon revision v0.2, 16MB external flash
Minimum free heap size: 390648 bytes
Restarting in 10 seconds...
Restarting in 9 seconds...
Restarting in 8 seconds...
Restarting in 7 seconds...
Restarting in 6 seconds...
Restarting in 5 seconds...
2
3
4
5
6
7
8
9
先输出 Hello world,然后打印了一些单片机信息,然后进入重启倒计时。
注意:使用 Ctrl 加中括号]键,可以关闭退出终端。
目前的工程文件如下图所示:
上图中,除了 main 和 CMakeLists.txt 文件,其它的全部都是配置和编译产生的文件,删除后可以重新配置编译生成。一般情况下,把工程传输给另外一个人
flash_download_tool 下载工具
刚才是在 VSCode 中直接下载程序,接下来看看使用 flash_download_tool 工具如何下载。
flash_download_tool 软件是乐鑫提供的下载软件,可以用于乐鑫所有型号芯片的程序下载。
flash_download_tool 下载地址:https://www.espressif.com.cn/zh-hans/support/download/other-tools
进入上面链接后,点击“Flash 下载工具”后面的下载按钮。
我下载的是 3.9.7 版本,版本号会不定时更新,不影响使用。
双击 flash_download_tool_3.9.7.exe 打开软件。
选择芯片型号(ChipType),工作模式(WordMode)选择开发模式(Develop)和工厂模式(Factory)都可以,开发模式界面用于下载一个开发板,工厂模式依次可以下载十个开发板,你用工厂模式下载一个开发板也是可以的。下载模式(LoadMode)选择串口(UART)。点击 OK 进入。
下面是开发模式界面。
在这个界面,需要加载你要下载的 bin 文件,配置 SPIFlash 相关信息,以及串口相关信息。
我们在使用 VSCode 下载程序时候,终端显示了下载过程的细节,如下图所示。你回到 VSCode 中,右下角点击“python 任务”,然后左边稍微上滑一点,就可以找到。
从上图中我们可以看到:
串口号选择 COM19,波特率是 460800。
Flash mode 是 DIO,Flash freq 是 80M,也就是 SPI SPEED。
0x0 位置下载 bootloader.bin 文件,0x10000 位置下载 hello_world.bin 文件,0x8000 位置下载 partition-table.bin 文件。
bootloader.bin 是启动文件,位于 bulid\bootloader 文件夹中。
hello_world.bin 是我们的应用程序文件,位于 bulid 文件夹中。
partition-table.bin 是分区表文件,位于 build\partition_table 文件夹中。分区表用于给 flash 划定分区,类似于 Windows 电脑的 C 盘 D 盘等分区。这里使用的是默认的分区表,默认的分区表在 menuconfig 中已经配置好,在之后的例程中,我们还会定义自己的分区表,在分区表中,还可以建立文件系统,下载 AI 模型。
除了上面的终端过程可以看到这些信息,在 build 文件夹下的 flash_args 文件中也可以看到,如下图所示。
按照上面的提示,就可以完成 flash_download_tool 上的配置,配置之前,你可以把所需要的 bin 文件复制到 flash_download_tool 软件的 bin 文件夹当中,方便加载,也可以不用复制,直接到工程文件夹加载。配置后如下所示。
配置好以后,点击左下角的 START,就开始下载了。
注意: 1、bin 文件前面的勾一定要勾上,才可以下载对应的 bin 文件。这意味着,你也可以在这里加载很多其它用于测试的 bin 文件,只要不勾选,就不会下载,勾选谁,下载谁。 2、程序下载完之后,程序不会自动运行。需要自己按一下复位键,或者给板子重新上电,程序才会运行。
如果你开发的项目已经完成,需要把程序交给生产人员去下载,可以把上面的三个 bin 文件合成一个 bin 文件,这样以后下载也比较方便。
合成一个 bin 文件的按钮是“CombineBin”,点击一下就合成好了,合成后的文件位于 flash_download_tool 软件的 combine 文件夹当中,名称默认是 target.bin,可以给它修改名称,比如这里改成 hello_world.bin,以后再下载,只需要加载这一个 bin 文件就可以了,如下图所示:
3.3 程序源码分析
接下来,我们分析一下源程序代码。
在 app_main 函数中,使用了好几个 printf 输出数据,结合刚才的输出内容,再对照这个程序代码,你就可以看懂了。
几个 printf 输出语句之后,跟了一个 fflush(stdout),fflush 是 C 语言库函数,使用这个库函数,需要头文件包含 <stdio.h> 文件。fflush(stdin)的作用是清空输入缓冲区,fflush(stdout)的作用是清空输出缓冲区,这里我们使用的是 fflush(stdout)。
printf 输出的内容,是先放在缓冲区的,遇到换行符\n 才会立即输出,如果没有换行符,它就不会及时输出,在没有换行符的情况下,使用 fflush(stdout)就会立即输出,不过,虽然会立即输出,它不会自动换行,要想自动换行,还得加换行符。
在这个例程中,我们去掉 fflush(stdout),依然会正常执行程序,是因为前面已经有换行符了,这里的 fflush 函数只起到一个保险作用。如果你想试试我们刚才说的内容,可以修改程序试一下。
void app_main(void)
{
while (1)
{
printf("Hello world!");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
// 这里注释掉不用的代码
}
2
3
4
5
6
7
8
9
void app_main(void)
{
while (1)
{
printf("Hello world!");
fflush(stdout);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
// 这里注释掉不用的代码
}
2
3
4
5
6
7
8
9
10
void app_main(void)
{
while (1)
{
printf("Hello world!\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
// 这里注释掉不用的代码
}
2
3
4
5
6
7
8
9
上面有 3 个代码片段,第 1 个是 printf 中没有加\n 换行符,编译下载后,你会看到 printf 没有及时输出内容,而是间隔一段时间输出一堆。第 2 个加了 fflush 函数,就可以间隔 1 秒输出了,不过没有换行。第 3 个加了换行符,在没有 fflush 函数的情况下,也可以正常及时输出。
注释代码,可以使用快捷键 Crtl 和/按键。先选中要注释的代码,然后按住 Crtl 键不要放,然后按一下/键,代码就会被注释,注意输入法要在英文状态下。如果想取消注释,也是 Ctrl 和/键。