很多数据是以文件形式存在的,如图片、音频、日志等,当我们需要操作此类数据时,就必须得有一个文件系统,在ESP32项目中,可以使用FLASH存储的一段区间来构建文件系统,也可以外持SD卡来做为文件系统。
FS类是ESP32库内置的文件系统基类,ESP32内置了多种文件系统实现,包括FFat,SPIFFSFS,SDFS等
Flash存储是有刷写次数寿命的,若使用场景需要频繁写入文件,请合理选择文件系统!
FileSystem类是本开发框架对FS类的简单封装,目地是隔离应用侧代码对FS类的依赖,这样有利于应用侧代码的移植和扩展。
在本开发框架中,类似这样的封装还有很多,有兴趣的同学可以参阅源码了解。
下面用两个例子来说明文件系统的使用
从 https://gitee.com/billyzh/esp32-cpp-lesson 下载本教程的源码到本地硬盘文件夹,如d:\esp32-cpp-lesson
在VSCode中,选择【文件】->【打开文件夹...】选择上一步保存的文件夹打开
本示例使用ESP32内置的FLASH存储区间构建Fat文件系统,并进行文件读写操作。
打开项目后,选择config.h文件,修改第10行为
#define APP_LESSON91_A 1
打开unit9-lesson91a/app_config.h文件,设置应用的相关配置
#define CONFIG_USE_FS 1 //启用文件系统模块
#define CONFIG_USE_DISPLAY 1 //启用显示模块
#define CONFIG_USE_TFT_ESPI 1 //使用TFT_eSPI显示驱动
打开unit9-lesson91a/board_config.h文件,设置硬件的相关配置
#define DISPLAY_WIDTH 320 //屏幕宽度像素
#define DISPLAY_HEIGHT 240 //屏幕高度像素
#define DISPLAY_INVERT_COLOR true //是否反转颜色
在ArduinoIDE中使用库管理器安装TFT_eSPI库
打开TFT_eSPI库文件夹内的User_Setup.h文件,修改以下设置:
1.删除行#define ST7789_DRIVER的//注释符,注释其他的芯片驱动;
2.设置引脚如下
#define TFT_MISO -1
#define TFT_MOSI 13
#define TFT_SCLK 12
#define TFT_CS 33 // 片选
#define TFT_DC 23
#define TFT_BL 5 // LED背光
#define TFT_RST 32
本节对TFT-LCD显示屏的引脚做了修改,原因是在前几节中TFT-LCD用到的引脚要用于其它设备。 引脚的合理分配也是设计的重要环节。
实现FileSystem实例,代码如下(unit9-lesson91a/my_board.cpp):
void MyBoard::InitFileSystem() {
Log::Info( TAG, "Init file system ......" );
if (!FFat.begin()) {
FFat.format();
if (!FFat.begin()) {
Log::Info(TAG, "FFat Mount Failed");
return;
}
}
filesystem_ = new FileSystem(FFat);
filesystem_->setTotalBytes(FFat.totalBytes());
filesystem_->setFreeBytes(FFat.freeBytes());
filesystem_->setType("ffat");
Log::Info(TAG, "init filesystem, type: %s, totalbytes: %ld, freebytes: %ld",
filesystem_->type().c_str(), filesystem_->totalBytes(), filesystem_->freeBytes());
}
程序解读
1.先使用内置FFat文件系统类进行初始化,它会将partitions.csv中ffat标签定义的存储区间构建为一个FFat文件系统。
2.创建FileSystem类实例,并用日志输出相关信息
注意:
1.如果ffat标签定义的存储区间之前是别的存储类型,那么重新格式化将导致数据丢失!
2.如果变更partitions分区文件中的区间值,那么可能会导致数据丢失!
3.如果开发板配置项“Erase All Flash Before Sketch Upload”设置为“true”,则会导致数据丢失!
文件读写代码如下(unit9-lesson91a/my_application.cpp):
void MyApplication::OnInit() {
Display *display = Board::GetInstance().GetDisplay();
display->Rotate(1);
FileSystem *fsys = Board::GetInstance().GetFileSystem();
if (fsys==nullptr) {
Log::Warn(TAG, "FileSystem init failed.");
display->GetWindow()->SetText(1, "FileSystem init failed.");
return;
}
char *path = "/hello.txt";
if (fsys->ExistsFile(path)) {
Log::Info(TAG, "read file.");
File f = fsys->OpenFile(path);
if (f) {
String content = f.readString();
display->GetWindow()->SetText(1, "File read success.");
display->GetWindow()->SetText(2, std::string(content.c_str()));
} else {
Log::Warn(TAG, "File %s read failed.", path);
display->GetWindow()->SetText(1, "File read failed.");
}
} else {
Log::Info(TAG, "create file.");
fsys->WriteFile(path, "Hello world!");
display->GetWindow()->SetText(1, "File create success.");
}
}
程序解读
1.通过Board实例取得FileSystem的实例;
2.若根目录存在hello.txt文件,则读取并显示在TFT-LCD显示屏上;
3.若文件不存在,则创建文件并写入“Hello world!”;
指定一个包含FAT存储的分区选项
编译项目并上传开发板检验

再次运行
使用FLASH存储做为文件系统容量相对较小(10M以内),若需要更大的存储空间,可以使用SD卡,不过SD卡的访问速度比FLASH要慢1~2个数量级。
本例使用的SD卡模块采用SPI协议 
SD存储模块详情
打开项目后,选择config.h文件,修改第10行为
#define APP_LESSON91_B 1
应用配置同前一小节。
打开unit9-lesson91b/board_config.h文件,添加以下SD卡配置
#define SD_MOSI_PIN GPIO_NUM_17
#define SD_MISO_PIN GPIO_NUM_16
#define SD_CLK_PIN GPIO_NUM_15
#define SD_CS_PIN GPIO_NUM_14
实现FileSystem实例,代码如下(unit9-lesson91b/my_board.cpp):
void MyBoard::InitFileSystem() {
Log::Info( TAG, "Init file system ......" );
SPI.begin(SD_CLK_PIN, SD_MISO_PIN, SD_MOSI_PIN, SD_CS_PIN);
if (!SD.begin(SD_CS_PIN)) {
Log::Info(TAG, "SD Mount Failed");
return;
}
filesystem_ = new FileSystem(SD);
filesystem_->setTotalBytes(SD.totalBytes());
filesystem_->setFreeBytes(SD.totalBytes() - SD.usedBytes());
filesystem_->setType("SD");
Log::Info(TAG, "init filesystem, type: %s, totalbytes: %ld, freebytes: %ld",
filesystem_->type().c_str(), filesystem_->totalBytes(), filesystem_->freeBytes());
}
程序解读
1.启动SPI协议
2.使用内置SD文件系统类进行初始化,SD卡可在电脑端进行格式化为FAT格式
2.创建FileSystem类实例,并用日志输出相关信息
文件读写代码如下(unit9-lesson91b/my_application.cpp):
代码同示例1
编译项目并上传开发板检验
I2S(Inter—IC Sound)总线, 又称集成电路内置音频总线,是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准。
MimiClaw 是一款基于 ESP32-S3 芯片的超轻量级AI助手,适合嵌入式AI与物联网开发者快速部署本地化AI代理。本系列教程基于MimiClaw的Arduino移植版本进行讲解,小节主要讲解部署和测试。
就像我们用手机打开WiFi功能后可以浏览附近的可用WiFi。要将手机连接到热点,通常需要打开Wi-Fi设置应用程序,列出可用的网络,然后选择所需的热点。然后输入密码(或不输入密码),可以使用ESP32进行相同的操作。
本文本介绍配置飞书机器人为MimiClaw的一个输入/输出端,和添加一个控制WS2812与LED的控制技能。
一块 30 块钱的开发板 + 一个大模型 API,就能做出可以听懂人话的智能硬件。 本文记录完整安装过程和踩坑经验,确保你跟着做就能跑通。
本文将从手绘架构图入手,逐层拆解 MimiClaw 的分层设计、核心模块、数据流转与底层实现,带你解剖这只“智能虾”的技术骨架,看懂在 C 语言加持下,AI 智能体如何以可穿戴设备的形态,在你身边稳稳运行、离线服务、主动响应。
本文介绍如何在不脱离 ArduinoIDE 可视化开发的前提下,通过一个名为 platform.local.txt 的小文件,实现对 ESP32 编译流程的精准控制。
本文将系统分析程序体积增长的五大根源,并提供经过验证的优化方案,帮助减小固件大小。
本文所DIY的语音助手设备端使用的是MicroPython、服务端是Python,对于很多开发者来说MicroPython入门没难度。
本小节使用音频开发框架实现一个音频录制到文件的示例。
I2S协议通过BCLK、LRCLK和DATA三线精准传输音频数据,但时序边沿、帧格式、时钟源等细节常引发噪声或断连。本文详解ESP32的I2S实现,从协议原理到ESP-IDF v5.x代码配置,助你避开常见陷阱,确保音频稳定传输。