欢迎光临
我们一直在努力

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有可能烧录不进去。

赞(0)
未经允许不得转载:171主机测评 » esp32开发与应用(esp32的tf卡读写)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址