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

esp32开发与应用(esp32的tf卡读写)

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

前面我们学习了esp32-s3的tf卡读写,今天想学习下esp32的tf卡读写。两者虽然功能差不多,但是前者比后者多一个usb口,所以成本上要贵一点的,所以我们有必要考虑下esp32是否也支持tf卡读写。答案是肯定的,不过有一些地方需要注意下。

1、确认模块电压

前面说过,电商网站买到的很多tf卡模块都是5v输入电压,并不是3.3v,这一点是需要注意的。

2、继续确认引脚连线

esp32和esp32-s3的引脚并不是完全一致的,所以直接用spi代替sdio配置tf卡的时候,一定要注意找到对应的spi引脚。不然就算代码是正确的,也有可能跑不起来。

3、调低spi速率

很多时候esp32-s3是ok的,但是esp32却不行。如果是5v也配置好了,连线也没有问题,tf卡本身也是大牌、并且小于32g,这个时候就要想办法降低spi的速率了,这样才可能读取到tf卡里面的内容。

4、通过ai生成代码

这一切都准备好之后,就可以让ai帮助我们生成代码了。可以这么说,用esp-idf生成一个esp32的tf卡读写demo。不出意外,就可以得到这样的代码。首先是CMakeLists.txt,

idf_component_register(SRCS "main.c" "sdcard_driver.c" INCLUDE_DIRS "." REQUIRES fatfs sdmmc driver )

接着是一个头文件sdcard_driver.h文件,

#ifndef SDCARD_DRIVER_H #define SDCARD_DRIVER_H #include "esp_err.h" #include "driver/gpio.h" // Pin definitions (modify according to your hardware connection) #define SD_PIN_CS GPIO_NUM_15 // Chip select #define SD_PIN_CLK GPIO_NUM_14 // Clock #define SD_PIN_MOSI GPIO_NUM_13 // Master Out Slave In #define SD_PIN_MISO GPIO_NUM_12 // Master In Slave Out // Mount point path #define SD_MOUNT_POINT "/sdcard" // Initialize SD card esp_err_t sdcard_init(void); // Unmount SD card void sdcard_unmount(void); // Write data to a file esp_err_t sdcard_write_file(const char* filename, const char* data); // Read data from a file esp_err_t sdcard_read_file(const char* filename, char* buffer, size_t buffer_size); // Append data to a file esp_err_t sdcard_append_file(const char* filename, const char* data); // Delete a file esp_err_t sdcard_delete_file(const char* filename); // Check if a file exists bool sdcard_file_exists(const char* filename); // Print SD card capacity information void sdcard_print_info(void); // List directory contents void sdcard_list_directory(const char* path); #endif // SDCARD_DRIVER_H

然后是sdcard_driver.c文件,

#include <stdio.h> #include <string.h> #include <sys/unistd.h> #include <sys/stat.h> #include <dirent.h> #include <errno.h> #include "esp_err.h" #include "esp_log.h" #include "esp_vfs_fat.h" #include "sdmmc_cmd.h" #include "driver/sdspi_host.h" #include "driver/spi_common.h" #include "sdcard_driver.h" static const char* TAG = "SDCARD"; static sdmmc_card_t* s_card = NULL; static bool s_is_mounted = false; esp_err_t sdcard_init(void) { esp_err_t ret; if (s_is_mounted) { ESP_LOGW(TAG, "SD card already mounted"); return ESP_OK; } ESP_LOGI(TAG, "Initializing SD card (SPI mode)"); ESP_LOGI(TAG, "Pin configuration: CS=%d, CLK=%d, MOSI=%d, MISO=%d", SD_PIN_CS, SD_PIN_CLK, SD_PIN_MOSI, SD_PIN_MISO); // Configure SPI bus spi_bus_config_t bus_config = { .mosi_io_num = SD_PIN_MOSI, .miso_io_num = SD_PIN_MISO, .sclk_io_num = SD_PIN_CLK, .quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = 4000, }; // Initialize SPI bus ret = spi_bus_initialize(SPI2_HOST, &bus_config, SPI_DMA_CH_AUTO); if (ret != ESP_OK) { ESP_LOGE(TAG, "SPI bus initialization failed: %s", esp_err_to_name(ret)); return ret; } // Configure SD SPI device sdspi_device_config_t slot_config = { .host_id = SPI2_HOST, .gpio_cs = SD_PIN_CS, .gpio_cd = GPIO_NUM_NC, .gpio_wp = GPIO_NUM_NC, .gpio_int = GPIO_NUM_NC, }; // Initialize SD SPI host driver ret = sdspi_host_init(); if (ret != ESP_OK) { ESP_LOGE(TAG, "SD SPI host initialization failed: %s", esp_err_to_name(ret)); spi_bus_free(SPI2_HOST); return ret; } // Configure host parameters sdmmc_host_t host = SDSPI_HOST_DEFAULT(); host.slot = SPI2_HOST; host.max_freq_khz = 10000; // 10MHz // Mount configuration esp_vfs_fat_sdmmc_mount_config_t mount_config = { .format_if_mount_failed = false, .max_files = 5, .allocation_unit_size = CONFIG_WL_SECTOR_SIZE }; // Mount file system ret = esp_vfs_fat_sdspi_mount(SD_MOUNT_POINT, &host, &slot_config, &mount_config, &s_card); if (ret != ESP_OK) { ESP_LOGE(TAG, "SD card mount failed: %s", esp_err_to_name(ret)); if (ret == ESP_FAIL) { ESP_LOGE(TAG, "File system mount failed, please check:"); ESP_LOGE(TAG, " 1. Whether the SD card is properly inserted"); ESP_LOGE(TAG, " 2. Whether the SD card is formatted as FAT/FAT32"); ESP_LOGE(TAG, " 3. Whether pin connections are correct"); ESP_LOGE(TAG, " 4. Try reducing SPI frequency"); } sdspi_host_deinit(); spi_bus_free(SPI2_HOST); return ret; } s_is_mounted = true; // Print SD card information sdcard_print_info(); return ESP_OK; } void sdcard_unmount(void) { if (!s_is_mounted) { ESP_LOGW(TAG, "SD card not mounted"); return; } esp_err_t ret = esp_vfs_fat_sdcard_unmount(SD_MOUNT_POINT, s_card); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to unmount SD card: %s", esp_err_to_name(ret)); } ret = sdspi_host_deinit(); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to deinitialize SD SPI host: %s", esp_err_to_name(ret)); } ret = spi_bus_free(SPI2_HOST); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to free SPI bus: %s", esp_err_to_name(ret)); } s_is_mounted = false; s_card = NULL; ESP_LOGI(TAG, "SD card unmounted"); } esp_err_t sdcard_write_file(const char* filename, const char* data) { if (!s_is_mounted) { ESP_LOGE(TAG, "SD card not mounted"); return ESP_FAIL; } char filepath[256]; snprintf(filepath, sizeof(filepath), "%s/%s", SD_MOUNT_POINT, filename); FILE* f = fopen(filepath, "w"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file: %s", filepath); return ESP_FAIL; } int bytes_written = fprintf(f, "%s", data); fclose(f); if (bytes_written < 0) { ESP_LOGE(TAG, "Failed to write file: %s", filepath); return ESP_FAIL; } ESP_LOGI(TAG, "File written successfully: %s (%d bytes)", filepath, bytes_written); return ESP_OK; } esp_err_t sdcard_read_file(const char* filename, char* buffer, size_t buffer_size) { if (!s_is_mounted) { ESP_LOGE(TAG, "SD card not mounted"); return ESP_FAIL; } char filepath[256]; snprintf(filepath, sizeof(filepath), "%s/%s", SD_MOUNT_POINT, filename); FILE* f = fopen(filepath, "r"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file: %s", filepath); return ESP_FAIL; } size_t bytes_read = fread(buffer, 1, buffer_size - 1, f); buffer[bytes_read] = '\0'; fclose(f); ESP_LOGI(TAG, "File read successfully: %s (%d bytes)", filepath, bytes_read); return ESP_OK; } esp_err_t sdcard_append_file(const char* filename, const char* data) { if (!s_is_mounted) { ESP_LOGE(TAG, "SD card not mounted"); return ESP_FAIL; } char filepath[256]; snprintf(filepath, sizeof(filepath), "%s/%s", SD_MOUNT_POINT, filename); FILE* f = fopen(filepath, "a"); if (f == NULL) { ESP_LOGE(TAG, "Failed to open file: %s", filepath); return ESP_FAIL; } int bytes_written = fprintf(f, "%s", data); fclose(f); if (bytes_written < 0) { ESP_LOGE(TAG, "Failed to append to file: %s", filepath); return ESP_FAIL; } ESP_LOGI(TAG, "Data appended successfully: %s (%d bytes)", filepath, bytes_written); return ESP_OK; } esp_err_t sdcard_delete_file(const char* filename) { if (!s_is_mounted) { ESP_LOGE(TAG, "SD card not mounted"); return ESP_FAIL; } char filepath[256]; snprintf(filepath, sizeof(filepath), "%s/%s", SD_MOUNT_POINT, filename); if (unlink(filepath) != 0) { ESP_LOGE(TAG, "Failed to delete file: %s", filepath); return ESP_FAIL; } ESP_LOGI(TAG, "File deleted successfully: %s", filepath); return ESP_OK; } bool sdcard_file_exists(const char* filename) { if (!s_is_mounted) { return false; } char filepath[256]; snprintf(filepath, sizeof(filepath), "%s/%s", SD_MOUNT_POINT, filename); struct stat st; return (stat(filepath, &st) == 0); } void sdcard_print_info(void) { if (!s_card) { ESP_LOGE(TAG, "SD card info not available"); return; } ESP_LOGI(TAG, "========== SD Card Information =========="); sdmmc_card_print_info(stdout, s_card); ESP_LOGI(TAG, "========================================="); } void sdcard_list_directory(const char* path) { if (!s_is_mounted) { ESP_LOGE(TAG, "SD card not mounted"); return; } char full_path[256]; if (path == NULL || strlen(path) == 0) { snprintf(full_path, sizeof(full_path), "%s", SD_MOUNT_POINT); } else if (path[0] == '/') { snprintf(full_path, sizeof(full_path), "%s", path); } else { snprintf(full_path, sizeof(full_path), "%s/%s", SD_MOUNT_POINT, path); } DIR* dir = opendir(full_path); if (dir == NULL) { ESP_LOGE(TAG, "Failed to open directory: %s, errno: %d", full_path, errno); return; } ESP_LOGI(TAG, "Directory: %s", full_path); struct dirent* entry; struct stat entry_stat; while ((entry = readdir(dir)) != NULL) { // Use safer length checking char entry_path[512]; // Increase buffer size int len = snprintf(entry_path, sizeof(entry_path), "%s/%s", full_path, entry->d_name); if (len < 0 || len >= (int)sizeof(entry_path)) { ESP_LOGW(TAG, "Path too long: %s/%s", full_path, entry->d_name); continue; } if (stat(entry_path, &entry_stat) == 0) { if (entry_stat.st_mode & S_IFDIR) { ESP_LOGI(TAG, " [DIR] %s", entry->d_name); } else { ESP_LOGI(TAG, " [FILE] %s (%ld bytes)", entry->d_name, entry_stat.st_size); } } else { ESP_LOGI(TAG, " %s", entry->d_name); } } closedir(dir); }

最后是main.c文件,整个内容稍微多一点,但是内容不复杂。

#include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" #include "sdcard_driver.h" static const char* TAG = "MAIN"; void sdcard_test_task(void* pvParameters) { esp_err_t ret; // Initialize SD card ret = sdcard_init(); if (ret != ESP_OK) { ESP_LOGE(TAG, "SD card initialization failed, stopping task"); vTaskDelete(NULL); return; } // Wait 1 second to ensure SD card is stable vTaskDelay(pdMS_TO_TICKS(1000)); // Test file write ESP_LOGI(TAG, "=== Test: Write File ==="); ret = sdcard_write_file("test.txt", "Hello, ESP-IDF SD Card!\nThis is a test file.\nLine 3: SPI mode test.\n"); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to write file"); } // Test file append ESP_LOGI(TAG, "=== Test: Append to File ==="); ret = sdcard_append_file("test.txt", "Appended line: Additional data.\n"); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to append to file"); } // Test file read ESP_LOGI(TAG, "=== Test: Read File ==="); char buffer[1024] = {0}; ret = sdcard_read_file("test.txt", buffer, sizeof(buffer)); if (ret == ESP_OK) { ESP_LOGI(TAG, "File content:\n%s", buffer); } else { ESP_LOGE(TAG, "Failed to read file"); } // Test file existence check ESP_LOGI(TAG, "=== Test: File Existence ==="); if (sdcard_file_exists("test.txt")) { ESP_LOGI(TAG, "File test.txt exists"); } else { ESP_LOGI(TAG, "File test.txt does not exist"); } if (sdcard_file_exists("nonexistent.txt")) { ESP_LOGI(TAG, "File nonexistent.txt exists"); } else { ESP_LOGI(TAG, "File nonexistent.txt does not exist"); } // Test creating multiple files ESP_LOGI(TAG, "=== Test: Create Multiple Files ==="); for (int i = 1; i <= 3; i++) { char filename[32]; char content[128]; snprintf(filename, sizeof(filename), "file_%d.txt", i); snprintf(content, sizeof(content), "This is file number %d\nCreated at: %lu\n", i, xTaskGetTickCount()); sdcard_write_file(filename, content); vTaskDelay(pdMS_TO_TICKS(100)); } // List SD card root directory ESP_LOGI(TAG, "=== Test: List SD Card Contents ==="); sdcard_list_directory("/sdcard"); // Test file deletion ESP_LOGI(TAG, "=== Test: Delete File ==="); ret = sdcard_delete_file("file_3.txt"); if (ret == ESP_OK) { ESP_LOGI(TAG, "Successfully deleted file_3.txt"); } // List directory again to confirm deletion sdcard_list_directory("/sdcard"); // Display SD card information sdcard_print_info(); ESP_LOGI(TAG, "SD card test completed, continuing to run..."); // Demonstrate periodic data writing int counter = 0; while (1) { vTaskDelay(pdMS_TO_TICKS(10000)); // Execute every 10 seconds char log_filename[64]; char log_content[256]; // Create log file named by counter (simplified version) snprintf(log_filename, sizeof(log_filename), "log_%d.txt", counter); snprintf(log_content, sizeof(log_content), "Log entry %d at tick: %lu\n", counter, xTaskGetTickCount()); if (sdcard_append_file(log_filename, log_content) == ESP_OK) { ESP_LOGI(TAG, "Log written successfully: %s", log_filename); } counter++; // Clean up old logs every 5 writes if (counter > 5) { char old_log[64]; snprintf(old_log, sizeof(old_log), "log_%d.txt", counter - 5); sdcard_delete_file(old_log); } } } void app_main(void) { ESP_LOGI(TAG, "ESP-IDF SD Card SPI Mode Driver Test"); ESP_LOGI(TAG, "System starting..."); // Create SD card test task xTaskCreate(sdcard_test_task, "sdcard_test", 8192, NULL, 5, NULL); // Main task can perform other operations while (1) { vTaskDelay(pdMS_TO_TICKS(60000)); // Print status every minute ESP_LOGI(TAG, "System running, SD card ready"); } }

5、测试和验证

代码都ok之后,老规矩,先看看能不能编译成功,再看看是否可以烧录,最后确认下是不是能够正常跑起来。这一切都没有问题之后,就意味着tf卡已经跑起来了。如果编译、烧录和运行过程中出现错误,还需要和ai继续沟通,看看问题是什么。

测试的时候,注意vs code左下角插件的位置,选择esp32,而不是esp32-s3,不然image有可能烧录不进去。

http://www.zskr.cn/news/1522672.html

相关文章:

  • MySQL高可用方案选型:MHA vs. Orchestrator vs. 云RDS,我们为什么最终选择了MHA?
  • 2026鄂州市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • 2026滨州市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • 如何快速提升SillyTavern性能:终极优化指南
  • 2026 广州奢侈品黄金回收店|耀辉无损鉴定设备实测解析 - 奢侈品回收
  • 2026楚雄本地贵金属变现门店精选前五+黄金铂金白银金条回收合规商家名录 含地址电话 - 诚金汇钻回收公司
  • 5分钟终极指南:用BepInEx游戏插件框架解锁无限游戏扩展能力
  • 中山优才教育联系方式怎么查?人工智能应用工程师报名 - 人工智能报名机构推荐
  • 2026巴中市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • 2026北京市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • 2026阿坝市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • 2026年 PFA隔膜阀/苏州隔膜阀厂家:高纯耐腐蚀性能与精密流体控制专业之选 - 品牌发掘
  • 2026年 江苏复合钢丝网/高精密网版厂家推荐榜:源头实力与工艺精度深度解析 - 品牌发掘
  • 2026上海奢侈品黄金回收细节封神榜!这家平台凭细节碾压全场 - 奢侈品回收
  • Vue+Golang实战:手把手教你给AI网站接入微信Native扫码支付(附完整代码)
  • 别再纠结了!Halcon和VisionMaster到底怎么选?从零到一帮你搞定机器视觉软件选型(附避坑清单)
  • 从‘半选’状态出发,聊聊Qt QSS伪状态选择器的那些‘冷门’但好用的写法(附QCheckBox实战)
  • 2026白山本地贵金属变现门店精选前五+黄金铂金白银金条回收合规商家名录 含地址电话 - 诚金汇钻回收公司
  • 2026深圳黄金回收行情详解:全城可接单当场打款,正规交易更安心 - 逸程
  • 从CSV到文件夹:用Python脚本把Mini-ImageNet改造成Keras/TF能直接用的分类数据集
  • 告别手动编译!Qt 5.12连接MySQL 8.0的三种“开箱即用”方案实测
  • 5分钟解锁QQ音乐加密音频:qmcdump让音乐自由播放
  • 2026深圳11区居民注意!黄金回收避坑指南:看懂大盘价不被随意压价 - 逸程
  • 2026朝阳本地贵金属变现门店精选前五+黄金铂金白银金条回收合规商家名录 含地址电话 - 诚金汇钻回收公司
  • 保姆级教程:从零在单节点Ubuntu上搭建DeepFlow可观测性平台(含Grafana面板配置)
  • CP、Tucker、BTD分解怎么选?一张图看懂三大张量分解算法的区别与应用场景
  • 从理论到实践:用Transformers的BitsAndBytes在消费级显卡上运行7B模型(内存计算与配置详解)
  • 2026本溪本地贵金属变现门店精选前五+黄金铂金白银金条回收合规商家名录 含地址电话 - 诚金汇钻回收公司
  • 3步构建高效抖音内容采集系统:开源项目实战指南
  • Wayland追求“每一帧都完美”,UI设计也应如此!