esp32开发与应用(添加数据分区)
2026/7/26 20:22:22 网站建设 项目流程

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

在esp32开发的时候,其实rom区域的大小是一定的。也就是说,code+data生成的bin文件大小是一定的。但是整个esp32的flash还是挺大的,所以如果要存储文件的话,最好是单独创建一个分区,然后操作这个分区即可。

1、调整flash大小

idf上面,默认flash的大小都是2m,所以需要在menuconfig下面,把flash大小调整为4m。在Serial Flash Config里面调整下即可。

2、创建partitions.csv文件

之前是没有这个文件的,现在需要单独创建这个文件。

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

3、csv文件的存放位置

csv文件放到prj根目录下即可,不需要放到main的子目录下。

4、用ai创建代码

为了验证分区是否ok,可以创建一个demo,比如录制一个10s的wav文件,放到这个分区,确认是否ok。如果整个流程没有问题的话,那么就说明分区是可以的。

#include <stdio.h> #include <string.h> #include <math.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" #include "esp_spiffs.h" #include "driver/i2s_pdm.h" static const char *TAG = "PDM_MIC"; // ------- Configuration ------- #define PDM_CLK_GPIO GPIO_NUM_4 #define PDM_DATA_GPIO GPIO_NUM_5 #define SAMPLE_RATE 16000 #define BITS_PER_SAMPLE 16 #define NUM_CHANNELS 1 #define RECORD_SECONDS 10 #define READ_CHUNK_SAMPLES 1024 // samples per read #define WAV_FILE_PATH "/spiffs/record.wav" static i2s_chan_handle_t rx_chan = NULL; // ---------- Standard 44-byte WAV header ---------- typedef struct __attribute__((packed)) { char riff_id[4]; // "RIFF" uint32_t riff_size; // file size - 8 char wave_id[4]; // "WAVE" char fmt_id[4]; // "fmt " uint32_t fmt_size; // 16 for PCM uint16_t audio_format; // 1 = PCM uint16_t num_channels; uint32_t sample_rate; uint32_t byte_rate; // sample_rate * num_channels * bits_per_sample/8 uint16_t block_align; // num_channels * bits_per_sample/8 uint16_t bits_per_sample; char data_id[4]; // "data" uint32_t data_size; // number of bytes of audio data } wav_header_t; static void wav_header_init(wav_header_t *h, uint32_t data_size) { memcpy(h->riff_id, "RIFF", 4); h->riff_size = data_size + sizeof(wav_header_t) - 8; memcpy(h->wave_id, "WAVE", 4); memcpy(h->fmt_id, "fmt ", 4); h->fmt_size = 16; h->audio_format = 1; // PCM h->num_channels = NUM_CHANNELS; h->sample_rate = SAMPLE_RATE; h->bits_per_sample = BITS_PER_SAMPLE; h->block_align = h->num_channels * h->bits_per_sample / 8; h->byte_rate = h->sample_rate * h->block_align; memcpy(h->data_id, "data", 4); h->data_size = data_size; } // ---------- SPIFFS init ---------- static void spiffs_init(void) { esp_vfs_spiffs_conf_t conf = { .base_path = "/spiffs", .partition_label = NULL, .max_files = 5, .format_if_mount_failed = true, }; ESP_ERROR_CHECK(esp_vfs_spiffs_register(&conf)); size_t total = 0, used = 0; esp_spiffs_info(NULL, &total, &used); ESP_LOGI(TAG, "SPIFFS mounted, total=%d used=%d", (int)total, (int)used); } // ---------- PDM mic init ---------- static void pdm_mic_init(void) { i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER); ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, NULL, &rx_chan)); i2s_pdm_rx_config_t pdm_rx_cfg = { .clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG(SAMPLE_RATE), .slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), .gpio_cfg = { .clk = PDM_CLK_GPIO, .din = PDM_DATA_GPIO, .invert_flags = { .clk_inv = false }, }, }; pdm_rx_cfg.slot_cfg.slot_mask = I2S_PDM_SLOT_LEFT; ESP_ERROR_CHECK(i2s_channel_init_pdm_rx_mode(rx_chan, &pdm_rx_cfg)); ESP_ERROR_CHECK(i2s_channel_enable(rx_chan)); ESP_LOGI(TAG, "PDM mic init done, CLK=%d, DATA=%d, %dHz", PDM_CLK_GPIO, PDM_DATA_GPIO, SAMPLE_RATE); } // ---------- Record N seconds to a WAV file ---------- static void record_wav_task(void *arg) { const uint32_t total_samples = SAMPLE_RATE * RECORD_SECONDS * NUM_CHANNELS; const uint32_t total_bytes = total_samples * (BITS_PER_SAMPLE / 8); FILE *f = fopen(WAV_FILE_PATH, "wb"); if (!f) { ESP_LOGE(TAG, "Failed to open %s for writing", WAV_FILE_PATH); vTaskDelete(NULL); return; } // Write a placeholder header first, fix up data_size after recording wav_header_t header; wav_header_init(&header, total_bytes); fwrite(&header, sizeof(header), 1, f); int16_t *buf = malloc(READ_CHUNK_SAMPLES * sizeof(int16_t)); if (!buf) { ESP_LOGE(TAG, "malloc failed"); fclose(f); vTaskDelete(NULL); return; } uint32_t bytes_written = 0; ESP_LOGI(TAG, "Recording %d seconds...", RECORD_SECONDS); while (bytes_written < total_bytes) { size_t bytes_read = 0; uint32_t bytes_remaining = total_bytes - bytes_written; size_t want = READ_CHUNK_SAMPLES * sizeof(int16_t); if (want > bytes_remaining) { want = bytes_remaining; // last chunk may be smaller } esp_err_t ret = i2s_channel_read(rx_chan, buf, want, &bytes_read, portMAX_DELAY); if (ret != ESP_OK) { ESP_LOGW(TAG, "i2s read err: %d", ret); continue; } fwrite(buf, 1, bytes_read, f); bytes_written += bytes_read; } fclose(f); free(buf); ESP_LOGI(TAG, "Recording done: %s (%d bytes audio data)", WAV_FILE_PATH, (int)bytes_written); vTaskDelete(NULL); } void app_main(void) { spiffs_init(); pdm_mic_init(); xTaskCreate(record_wav_task, "record_wav_task", 4096, NULL, 5, NULL); }

5、编译测试

编译的话,就按照一般的idf编译方法去处理就好了。调试的话,主要看打印。可以看到,第一次spiffs mount不成功,还会格式化一下。后续再调试的话,就直接加载了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询