1. ESP32与SPIFFS初探

各位同学,欢迎来到这门实战课。我是你们的老朋友,一个在嵌入式圈子里摸爬滚打了十几年的工程师。

第一节课,咱们不急着写复杂的Web服务器。先把地基打牢——认识一下ESP32这颗芯片,把开发环境搭好,再搞明白SPIFFS是个什么东西。最后,跑一个读写文件的例子,让你亲眼看到数据存进了Flash里。

1.1 ESP32开发板:不只是Wi-Fi+蓝牙

ESP32是乐鑫科技推出的双核芯片。说实话,我第一次拿到它的时候,第一反应是:这玩意儿性价比也太高了。双核240MHz处理器、520KB SRAM、Wi-Fi、蓝牙,还带一堆外设接口,价格却只有同级别ARM芯片的零头。

参数 ESP32-WROOM-32 ESP32-S3 ESP32-C3
核心架构 双核 Xtensa LX6 双核 Xtensa LX7 单核 RISC-V
主频 240 MHz 240 MHz 160 MHz
SRAM 520 KB 512 KB 400 KB
Flash 4~16 MB 8~16 MB 4 MB
Wi-Fi 802.11 b/g/n 802.11 b/g/n 802.11 b/g/n
蓝牙 BLE + Classic BLE 5.0 BLE 5.0

我个人习惯用ESP32-WROOM-32做原型验证。为什么?因为资料最多,踩过的坑别人都帮你填平了。你如果刚入门,选这个型号最稳妥。

选板建议: 买开发板时注意看Flash大小。至少4MB起步,因为后面我们要存网页文件。8MB或16MB更宽裕。

1.2 Arduino IDE环境搭建

搭建环境这事儿,说简单也简单,说烦也烦。我见过太多新手卡在这一步。别急,按我的步骤来,十分钟搞定。

步骤一:安装Arduino IDE

去官网下载最新版。Windows用户选Windows Installer,macOS用户选macOS版本。装完打开,界面很清爽。

步骤二:添加ESP32开发板支持

打开 文件 → 首选项,在“附加开发板管理器网址”里填入:

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

然后打开 工具 → 开发板 → 开发板管理器,搜索“ESP32”,找到由Espressif Systems提供的那个,点击安装。这个过程会下载几百兆的编译工具链,网速慢的话,泡杯茶等一会儿。

步骤三:选择开发板并测试

装好后,在 工具 → 开发板 里找到你的板型。我一般选“ESP32 Dev Module”。然后插上USB线,选好端口,点一下上传按钮。如果看到“Connecting...”然后成功烧录,恭喜你,环境通了。

我曾经踩过的坑: 有些便宜的USB转串口芯片(比如CH340G)在macOS上需要额外装驱动。如果你上传时提示“No serial data received”,先检查驱动。

1.3 SPIFFS文件系统概念

SPIFFS,全称SPI Flash File System。说白了,就是在ESP32的Flash芯片上划出一块区域,专门用来存文件。你可以把它理解成一个微型硬盘,只不过读写速度慢一些,容量也小一些。

为什么要用SPIFFS?你想想看,如果我们要做一个Web服务器,HTML、CSS、JavaScript这些文件放哪儿?总不能全写在代码里吧?那代码得膨胀成什么样。用SPIFFS,把这些静态文件单独存起来,程序运行时按需读取,既清晰又高效。

ESP32 Flash 分区结构图 ESP32 Flash (4MB / 8MB / 16MB) 引导加载程序 Bootloader 分区表 Partition Table 应用程序 App (OTA_0) SPIFFS 文件系统区域 存储 HTML / CSS / JS / 图片 / 配置文件 SPIFFS 分区大小可在编译时配置,通常为 1MB ~ 2MB

SPIFFS有几个特点,我简单列一下:

  • 基于Flash:掉电不丢失,适合存配置和网页文件
  • 类FAT操作:可以用open/read/write/close这些你熟悉的API
  • 磨损均衡:自动管理擦写次数,延长Flash寿命
  • 容量限制:单个文件最大约2MB,总大小取决于分区配置
核心概念: SPIFFS不是用来存代码的。代码烧录在另一个分区。SPIFFS只存数据文件。两者互不干扰。

1.4 第一个SPIFFS读写示例

光说不练假把式。咱们直接上手写代码。这个例子会做三件事:写入一段文本到SPIFFS,再读出来,最后打印到串口监视器。

准备工作:安装SPIFFS上传工具

在Arduino IDE中,打开 工具 → 管理库,搜索“SPIFFS”,安装“ESP32 SPIFFS”库。或者直接用Arduino ESP32核心自带的SPIFFS.h头文件。

代码示例

#include <SPIFFS.h>

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("SPIFFS 读写测试开始...");

  // 挂载文件系统
  if (!SPIFFS.begin(true)) {
    Serial.println("SPIFFS 挂载失败!");
    return;
  }
  Serial.println("SPIFFS 挂载成功");

  // 写入文件
  File file = SPIFFS.open("/hello.txt", FILE_WRITE);
  if (!file) {
    Serial.println("打开文件写入失败");
    return;
  }
  file.println("Hello, SPIFFS!");
  file.println("这是第一行数据");
  file.close();
  Serial.println("写入完成");

  // 读取文件
  file = SPIFFS.open("/hello.txt", FILE_READ);
  if (!file) {
    Serial.println("打开文件读取失败");
    return;
  }
  Serial.println("文件内容如下:");
  while (file.available()) {
    Serial.write(file.read());
  }
  file.close();
  Serial.println("\n读取完成");
}

void loop() {
  // 空循环,啥也不干
}

运行结果

上传代码后,打开串口监视器(波特率115200),你会看到类似这样的输出:

SPIFFS 读写测试开始...
SPIFFS 挂载成功
写入完成
文件内容如下:
Hello, SPIFFS!
这是第一行数据
读取完成
小技巧: SPIFFS.begin(true) 里的 true 参数表示“如果文件系统损坏,自动格式化”。第一次用建议加上,后面稳定了可以去掉。

代码解析

  • SPIFFS.begin():挂载文件系统。返回true表示成功。
  • SPIFFS.open(path, mode):打开文件。mode可以是FILE_READ或FILE_WRITE。
  • file.println():写入一行文本,自动加换行符。
  • file.available():检查还有多少字节可读。
  • file.read():读取一个字节。
  • file.close():关闭文件。这一步很重要,不关的话可能丢数据。
我曾经犯过的错: 有一次忘了调file.close(),结果写进去的文件只有一半内容。排查了半天才发现是文件句柄没释放。记住,打开文件后一定要关闭,就像出门要锁门一样。

本章小结

这一章我们干了三件事:认识了ESP32这颗芯片,搭好了Arduino IDE开发环境,搞懂了SPIFFS是什么,还亲手跑了一个读写文件的例子。嗯,基础打牢了,后面才能盖高楼。

你可能会问:就这?一个简单的读写就完了?别急,这才第一节课。后面我们会用SPIFFS存HTML文件,用ESP32当Web服务器,再整合各种传感器驱动。路还长,咱们一步一步走。