单片机/MCU论坛
直播中

刘勇

8年用户 1420经验值
私信 关注
[问答]

使用 emfile 库读取/写入外部 SD 卡遇到的问题求解

我正在使用 emfile 库读取/写入外部 SD 卡,但遇到了一个挑战,那就是 emfile 库没有 SPI 驱动程序。有人可以帮我实现一个 spi 驱动程序来在我的 SD 上执行读/写过程吗?
我正在使用 PSOC6(CY8CPROTO-063-BLE)

回帖(1)

刘杰

2025-8-6 18:17:45

为了在 PSoC6 (CY8CPROTO-063-BLE) 上通过 SPI 接口驱动 SD 卡并与 emFile 库集成,你需要实现一个自定义的 SPI 驱动层。以下是完整的解决方案:


步骤 1:配置 SPI 外设(PSoC Creator / ModusToolbox)


在 PSoC 开发环境中配置 SPI 外设:



  1. 配置 SPI 主模式(MOSI, MISO, SCK)

  2. 分配引脚:

    • SD_SCK -> SCK (P6.0)

    • SD_MOSI -> MOSI (P6.1)

    • SD_MISO -> MISO (P6.2)

    • SD_CS -> 自定义 GPIO (P6.3)

    • (可选)SD_CD 卡检测引脚 (P6.4)


  3. 设置 SPI 参数:

    • 模式: 0 (CPOL=0, CPHA=0)

    • 初始化频率:400 kHz (SD 卡初始化要求)

    • 最大频率:20-25 MHz(初始化后切换)



步骤 2:实现 SPI 驱动接口 (spi_sd.c)


#include "cyhal.h"
#include "cybsp.h"
#include "emFile_config.h" // emFile 配置文件

// 定义 SPI 对象和引脚
static cyhal_spi_t spi_sd;
static cyhal_gpio_t cs_pin = P6_3;

// SPI 初始化 (由 emFile 调用)
int SD_Init(void) {
    cy_rslt_t result;

    // 配置 SPI
    cyhal_spi_cfg_t spi_cfg = {
        .data_mode = CYHAL_SPI_MODE_00_MSB,
        .submode = CYHAL_SPI_MOTOROLA,
        .sclk_mode = CYHAL_SPI_SCLK_LOW_EDGE,
        .ssel = CYHAL_SPI_SSEL_NONE, // 手动控制 CS
        .is_slave = false,
        .fifo_width = CYHAL_SPI_WIDTH_8,
        .bits_per_frame = 8,
    };

    // 初始化 SPI
    result = cyhal_spi_init(&spi_sd, P6_1, P6_2, P6_0, NC, NULL, &spi_cfg);
    if(result != CY_RSLT_SUCCESS) return -1;

    // 配置片选引脚
    result = cyhal_gpio_init(cs_pin, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, 1);
    if(result != CY_RSLT_SUCCESS) return -2;

    // 设置低速(初始化阶段)
    cyhal_spi_set_frequency(&spi_sd, SD_INIT_SPI_FREQ);

    return 0;
}

// 发送/接收单字节 (emFile 基本操作)
BYTE SD_ReadWrite(BYTE out) {
    uint8_t in = 0;
    cyhal_spi_transfer(&spi_sd, &out, 1, &in, 1, 0);
    return in;
}

// 控制片选信号 (emFile 要求)
void SD_CS(BOOL state) {
    cyhal_gpio_write(cs_pin, state ? 0 : 1); // 低电平有效
}

// 高速切换 (初始化完成后调用)
void SD_SetHighSpeed(void) {
    cyhal_spi_set_frequency(&spi_sd, SD_HIGH_SPI_FREQ); // 20-25 MHz
}

// 块数据传输 (优化性能)
void SD_ReadWriteMulti(const BYTE* out, BYTE* in, int count) {
    cyhal_spi_transfer(&spi_sd, out, count, in, count, 0);
}

// 延迟函数
void SD_Delay(unsigned int ms) {
    cyhal_system_delay_ms(ms);
}

步骤 3:配置 emFile (FS_ConfigIO.h)


/* SPI 接口配置 */
#define FS_SPI_INTERFACE_SUPPORT  1  // 启用 SPI 接口
#define FS_USE_SPI_DRIVER         1  // 使用自定义驱动

/* 连接到 spi_sd.c 的实现 */
extern int  SD_Init(void);
extern void SD_CS(BOOL state);
extern BYTE SD_ReadWrite(BYTE data);
extern void SD_ReadWriteMulti(const BYTE* pOut, BYTE* pIn, int count);
extern void SD_Delay(unsigned int ms);
extern void SD_SetHighSpeed(void);

/* 接口映射 */
#define SPI_INIT          SD_Init
#define SPI_CS_LOW()      SD_CS(1)
#define SPI_CS_HIGH()     SD_CS(0)
#define SPI_RW            SD_ReadWrite
#define SPI_RW_MULTI      SD_ReadWriteMulti
#define SPI_DELAY         SD_Delay
#define SPI_SET_HIGH_SPEED SD_SetHighSpeed

步骤 4:SD 卡初始化流程


在应用程序中实现 SD 卡初始化序列:


#include "FS.h"

void init_sdcard() {
    // 1. 初始化SPI接口
    if(FS_InitInterface(0) != 0) {
        printf("SPI init failed!");
        return;
    }

    // 2. 检测并初始化SD卡
    if(FS_Init(0) != 0) {
        printf("SD init failed!");
        return;
    }

    // 3. 切换到高速模式(成功初始化后)
    SPI_SET_HIGH_SPEED();

    // 4. 挂载文件系统
    if(FS_Mount(0, 0) != 0) {
        printf("Mount failed!");
    }
}

关键注意事项:




  1. SPI 模式要求



    • 必须支持模式0 (CPOL=0, CPHA=0)

    • CS 信号在数据传输期间保持低电平




  2. 初始化序列



    • 先以 ≤400 kHz 频率初始化

    • 执行 CMD0 (GO_IDLE_STATE)

    • 处理 CMD8, ACMD41 等初始化命令

    • 初始化完成后切换到高速模式




  3. 数据处理



    • 单字节传输用于命令响应

    • 块传输(多字节)用于数据读写

    • 读写期间保持 CS 有效




  4. 硬件连接确认


    PSoC6       SD卡模块
    -------------------
    P6.0  -->   SCK
    P6.1  -->   MOSI
    P6.2  <--   MISO
    P6.3  -->   CS
    3.3V  -->   VCC
    GND   -->   GND



5. 调试技巧:



  • 使用逻辑分析仪检查 SPI 信号

  • 初始阶段确保时钟 ≤400 kHz

  • 检查所有命令的响应:

    • CMD0 应返回 0x01 (IDLE)

    • CMD8 确认电压范围

    • ACMD41 完成初始化(返回0x00)



完成上述步骤后,emFile 库就能通过 SPI 驱动访问 SD 卡。实际使用中可能需要根据 SD 卡型号调整初始化参数和时序,具体参考 SD 物理层规范文档。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分