当前位置: 首页 > news >正文

spiffs分区文件系统在esp idf的创建

我用的是vscdoe,为了测试一个ns4168的音频播放,我使用了spiffs分区来存储wav文件。

创建分区开始。

首先要求在配置文件中打开spiffs分区功能。

这个要拉倒最下面才看到

然后就是有时候如果配置里看不到,

REQUIRES driver spiffs  # 关键:添加 spiffs 依赖

这个是加载main目录里的cmake配置文件

如果配置文件没有选项可以通过CMakeLists设置

再下来就是把分区表设定为自定义的

分区表大家都懂,在根目录下面

内容我给个例子

# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x6000,
phy_init, data, phy,     0xf000,  0x1000,
factory,  app,  factory, 0x10000, 1M,
spiffs,   data, spiffs,  , 3M , 

也可以指定分区地址哈

# ESP-IDF Partition Table
# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,    0x4000,
otadata,  data, ota,     0xd000,    0x2000,
phy_init, data, phy,     0xf000,    0x1000,
model,    data, spiffs,  0x10000,   0xF0000,
ota_0,    app,  ota_0,   0x100000,  6M,
ota_1,    app,  ota_1,   0x700000,  6M,
spiffs,   data, spiffs,  0xD00000,  1M

类似于这种。都行。

然后最关键的一步,要在根目录下面的CMakeLists.txt添加自动烧录的配置。放在project项目后面。

# 配置 SPIFFS 自动烧录(关键代码)
spiffs_create_partition_image(spiffs data FLASH_IN_PROJECT)

这个时候在根目录下创建data文件夹,把你要的内容放进去就行了。

然后,清空项目,烧录,写个测试代码看看


// -------------------------- SPIFFS初始化 --------------------------
esp_err_t spiffs_init(void) {ESP_LOGI(TAG, "Initializing SPIFFS");esp_vfs_spiffs_conf_t conf = {.base_path = "/spiffs",.partition_label = NULL,.max_files = 5,.format_if_mount_failed = true};// 使用所有默认参数挂载SPIFFSesp_err_t ret = esp_vfs_spiffs_register(&conf);if (ret != ESP_OK) {if (ret == ESP_FAIL) {ESP_LOGE(TAG, "Failed to mount or format filesystem");} else if (ret == ESP_ERR_NOT_FOUND) {ESP_LOGE(TAG, "Failed to find SPIFFS partition");} else {ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));}return ret;}size_t total = 0, used = 0;ret = esp_spiffs_info(NULL, &total, &used);if (ret != ESP_OK) {ESP_LOGE(TAG, "Failed to get SPIFFS partition info (%s)", esp_err_to_name(ret));esp_vfs_spiffs_unregister(NULL);return ret;}ESP_LOGI(TAG, "SPIFFS initialized, total: %d, used: %d", total, used);return ESP_OK;
}// 在代码中添加列出文件的测试函数
void AudioCodec::list_spiffs_files() {DIR *dir = opendir("/spiffs");if (dir == NULL) {ESP_LOGE(TAG, "Failed to open directory");return;}struct dirent *ent;while ((ent = readdir(dir)) != NULL) {ESP_LOGI(TAG, "File: %s", ent->d_name);}closedir(dir);
}

如果有内容,说明ok了。

调用就直接调用

    // 1. 打开WAV文件FILE *wav_fp = fopen(wav_path, "rb");if (!wav_fp) {ESP_LOGE(TAG, "无法打开文件: %s", wav_path);return ESP_FAIL;}// 2. 获取文件总大小fseek(wav_fp, 0, SEEK_END);size_t total_size = ftell(wav_fp);rewind(wav_fp);

------------------------------------------------------------

我贴出来整个音频测试项目文件。

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s_std.h"
#include "driver/gpio.h"
#include "esp_err.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "esp_vfs.h"
#include "esp_spiffs.h"  // 添加SPIFFS支持// -------------------------- 配置参数(根据硬件修改) --------------------------
#define TAG             "WAV_PLAYER"
#define I2S_BCLK        GPIO_NUM_15  // I2S时钟线引脚
#define I2S_WS          GPIO_NUM_16  // I2S声道选择线(LRCK)引脚
#define I2S_DOUT        GPIO_NUM_7   // I2S数据输出引脚
#define PLAY_BUFFER_SIZE 2048        // 播放缓冲区大小(2KB,可按需调整)
#define WAV_SAMPLE_RATE 16000        // 目标WAV采样率(16kHz,需与播放文件匹配)
#define WAV_BIT_DEPTH   16           // 目标WAV位深(16bit,需与播放文件匹配)// 全局I2S播放通道句柄(供初始化和播放任务共用)
static i2s_chan_handle_t tx_chan = NULL;// -------------------------- I2S初始化(仅播放配置) --------------------------
/*** @brief 初始化I2S硬件(适配16kHz/16bit WAV播放)* @return ESP_OK: 成功;其他: 失败*/
esp_err_t ns4168_init(void) {// 1. 配置I2S播放通道(主模式)i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);esp_err_t err = i2s_new_channel(&tx_chan_cfg, &tx_chan, NULL);if (err != ESP_OK) {ESP_LOGE(TAG, "Failed to create I2S TX channel: %s", esp_err_to_name(err));return err;}// 2. 配置I2S标准模式(适配16kHz/16bit/立体声,若WAV是单声道需修改SLOT_MODE)i2s_std_config_t std_cfg = {.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(WAV_SAMPLE_RATE),  // 采样率匹配WAV文件.slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT,  // 位深匹配16bitI2S_SLOT_MODE_MONO       // 若播放单声道WAV,改为I2S_SLOT_MODE_MONO),.gpio_cfg = {.mclk = I2S_GPIO_UNUSED,  // 多数音频放大器无需MCLK,按需启用.bclk = I2S_BCLK,.ws = I2S_WS,.dout = I2S_DOUT,.din = I2S_GPIO_UNUSED,   // 播放无需输入,禁用DIN引脚.invert_flags = {.mclk_inv = false,.bclk_inv = false,.ws_inv = false,},},};// 3. 初始化I2S模式并启用通道err = i2s_channel_init_std_mode(tx_chan, &std_cfg);if (err != ESP_OK) {ESP_LOGE(TAG, "Failed to init I2S std mode: %s", esp_err_to_name(err));return err;}ESP_LOGI(TAG, "I2S init success (16kHz/16bit)");return ESP_OK;
}// -------------------------- WAV播放任务 --------------------------
/*** @brief 读取WAV文件并通过I2S播放* @param args: WAV文件路径(SPIFFS中的路径)*/
static void i2s_play_task(void *args) {const char *wav_path = (const char *)args;if (wav_path == NULL || tx_chan == NULL) {ESP_LOGE(TAG, "Invalid play params (path=%p, tx_chan=%p)", wav_path, tx_chan);vTaskDelete(NULL);return;}// 1. 分配播放缓冲区(栈外分配,避免栈溢出)uint8_t *play_buf = (uint8_t *)malloc(PLAY_BUFFER_SIZE);if (play_buf == NULL) {ESP_LOGE(TAG, "Failed to malloc play buffer (%d bytes)", PLAY_BUFFER_SIZE);vTaskDelete(NULL);return;}memset(play_buf, 0, PLAY_BUFFER_SIZE);// 2. 打开WAV文件(从SPIFFS读取)FILE *wav_fp = fopen(wav_path, "rb");if (wav_fp == NULL) {ESP_LOGE(TAG, "Failed to open WAV file: %s", wav_path);free(play_buf);vTaskDelete(NULL);return;}ESP_LOGI(TAG, "Open WAV file success: %s", wav_path);// 3. 跳过WAV文件头(标准WAV头为44字节,若文件有扩展头需调整)fseek(wav_fp, 44, SEEK_SET);// 4. 启用I2S播放通道并开始播放esp_err_t err = i2s_channel_enable(tx_chan);if (err != ESP_OK) {ESP_LOGE(TAG, "Failed to enable I2S channel: %s", esp_err_to_name(err));fclose(wav_fp);free(play_buf);vTaskDelete(NULL);return;}size_t read_bytes = 0;   // 从文件读取的字节数size_t written_bytes = 0;// I2S实际写入的字节数ESP_LOGI(TAG, "Start playing WAV...");// 循环读取WAV数据并播放while (1) {// 从文件读取数据到缓冲区read_bytes = fread(play_buf, 1, PLAY_BUFFER_SIZE, wav_fp);if (read_bytes == 0) {ESP_LOGI(TAG, "End of WAV file (read all data)");break;}// 将缓冲区数据通过I2S发送(阻塞等待发送完成)err = i2s_channel_write(tx_chan, play_buf, read_bytes, &written_bytes, portMAX_DELAY);if (err != ESP_OK) {ESP_LOGE(TAG, "I2S write failed: %s", esp_err_to_name(err));break;}ESP_LOGD(TAG, "Play progress: read=%d bytes, written=%d bytes", (int)read_bytes, (int)written_bytes);// 若读取的字节数小于缓冲区大小,说明文件已读完if (read_bytes < PLAY_BUFFER_SIZE) {ESP_LOGI(TAG, "Partial buffer read, play complete");break;}}// 5. 播放完成,清理资源i2s_channel_disable(tx_chan);  // 禁用I2S通道fclose(wav_fp);                // 关闭WAV文件free(play_buf);                // 释放缓冲区ESP_LOGI(TAG, "WAV play task finished");vTaskDelete(NULL);
}// -------------------------- SPIFFS初始化 --------------------------
esp_err_t spiffs_init(void) {ESP_LOGI(TAG, "Initializing SPIFFS");esp_vfs_spiffs_conf_t conf = {.base_path = "/spiffs",.partition_label = NULL,.max_files = 5,.format_if_mount_failed = true};// 使用所有默认参数挂载SPIFFSesp_err_t ret = esp_vfs_spiffs_register(&conf);if (ret != ESP_OK) {if (ret == ESP_FAIL) {ESP_LOGE(TAG, "Failed to mount or format filesystem");} else if (ret == ESP_ERR_NOT_FOUND) {ESP_LOGE(TAG, "Failed to find SPIFFS partition");} else {ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));}return ret;}size_t total = 0, used = 0;ret = esp_spiffs_info(NULL, &total, &used);if (ret != ESP_OK) {ESP_LOGE(TAG, "Failed to get SPIFFS partition info (%s)", esp_err_to_name(ret));esp_vfs_spiffs_unregister(NULL);return ret;}ESP_LOGI(TAG, "SPIFFS initialized, total: %d, used: %d", total, used);return ESP_OK;
}// 在代码中添加列出文件的测试函数
void list_spiffs_files() {DIR *dir = opendir("/spiffs");if (dir == NULL) {ESP_LOGE(TAG, "Failed to open directory");return;}struct dirent *ent;while ((ent = readdir(dir)) != NULL) {ESP_LOGI(TAG, "File: %s", ent->d_name);}closedir(dir);
}// -------------------------- 主函数 --------------------------
void app_main(void) {// 1. 初始化SPIFFS文件系统esp_err_t spiffs_err = spiffs_init();if (spiffs_err != ESP_OK) {ESP_LOGE(TAG, "SPIFFS init failed, exit app");return;}// 2. 初始化I2S播放硬件esp_err_t init_err = ns4168_init();if (init_err != ESP_OK) {ESP_LOGE(TAG, "I2S init failed, exit app");return;}list_spiffs_files();  // 列出 SPIFFS 中的文件// 3. 启动播放任务(使用SPIFFS中的文件路径)const char *target_wav = "/spiffs/hi_idf_audio.wav";  // SPIFFS中的WAV文件路径xTaskCreate(i2s_play_task, "i2s_play_task", 4096, (void *)target_wav, 5, NULL);
}

http://www.dtcms.com/a/411248.html

相关文章:

  • php网站开发技术描述南昌seo网站排名
  • html5微网站做网站原型图软件
  • 86-python电网可视化项目-6
  • 长乐住房和城乡建设局网站wordpress文章页面
  • 技术拐点将至:AI 大模型的挑战突围与产业重构
  • 青海省住房和城乡建设部网站关键词排名优化软件价格
  • 图片做多的网站是哪个邢台移动网站设计
  • TypeScript 中避免使用 @ts-ignore 的最佳方案
  • 数据传输一致性保障:如何避免‘少数据’或‘脏数据’?
  • Product Hunt 每日热榜 | 2025-09-26
  • 北京公司网站建设定制全国十大装修公司最有名的是
  • 鸿蒙开发入门经验分享:从零开始构建自己的HarmonyOS应用(ArkTS)
  • 解锁安全新维度:Cybersecurity AI (CAI) 助力提升网络安全效率!
  • FastAPI WebSocket 由浅入深的开发范例
  • 义乌免费做网站怎么创业呢白手起家
  • 网站维护运营好做吗建筑工程网络数据安全管理系统
  • 怎么制作外贸网站模板wordpress给会员发信
  • 西安跨境电商平台网站淘宝网网站设计分析
  • SSL 证书的重要性
  • 快速上手XXL-JOB
  • 分组交换总结
  • 亚马逊网站怎么做做网站一般注册商标哪个类
  • daily notes[54]
  • 机器学习——决策树详解
  • 万象EXCEL开发(六)excel单元格运算逻辑 ——东方仙盟金丹期
  • Redis数据结构和常用命令
  • 网站开发用什么开发无锡新吴区建设环保局网站
  • 深圳易捷网站建设计算机(网站建设与维护)
  • 智能微电网 —— 如何无缝集成分布式光伏 / 风电?
  • 苏州网站建设的公司万维网