学习STM32的SD卡读写

/**

  • 本代码案例将演示如何通过STM32读写SD卡。我们将使用SDIO接口和FATFS文件系统库来实现这一功能。
  • 步骤概述:
    1. 初始化SD卡接口(SDIO)
    1. 挂载文件系统
    1. 创建、写入和读取文件
  • 硬件要求:
    • 一个STM32单片机开发板(例如:STM32F4Discovery)
    • 一个带有SD卡插槽的SD卡模块
  • 软件要求:
    • STM32CubeMX:用于生成STM32项目的初始化代码
    • STM32CubeIDE:用于编写和调试STM32代码
    • FATFS库:用于支持SD卡的文件系统操作
  • 注意事项:
    • 在运行此代码之前,请确保已将SD卡正确连接到STM32开发板,并使用正确的引脚和电压级别。
    • 在STM32CubeMX中配置SD卡初始化,并将相关代码复制到main.c文件中。
    • 在STM32CubeIDE中添加FATFS库,并将相关代码复制到main.c文件中。
    • 在FATFS库的diskio.c文件中,根据SD卡的初始化配置修改SD卡的片选引脚。 */

#include "stm32f4xx_hal.h" #include "ff.h" #include "string.h"

// 定义SD卡的片选引脚 #define SD_CS_GPIO_Port GPIOB #define SD_CS_Pin GPIO_PIN_0

// 定义文件名和缓冲区 #define FILENAME "test.txt" #define BUFFER_SIZE 512 uint8_t buffer[BUFFER_SIZE];

// FATFS和文件句柄 FATFS fs; FIL fil;

// SD卡错误标志 volatile DSTATUS sdCardStatus = STA_NOINIT;

/**

  • 初始化SD卡接口 */ void SD_Init() { // 根据SD卡的初始化配置进行相应的初始化操作 // 这部分由STM32CubeMX生成的代码负责 MX_SDIO_SD_Init(); }

/**

  • SD卡选中 */ void SD_Select() { HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_RESET); }

/**

  • SD卡取消选中 */ void SD_Deselect() { HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_SET); }

/**

  • 通过SDIO接口向SD卡发送命令

  • @param cmd 命令宏定义

  • @param arg 命令参数

  • @param response 得到的响应

  • @return 成功或失败标志 */ int SD_SendCommand(uint8_t cmd, uint32_t arg, uint8_t *response) { SDIO_CmdInitTypeDef cmdInit; uint32_t responseVal = 0;

    // 初始化命令结构体 cmdInit.Argument = arg; cmdInit.CmdIndex = cmd; cmdInit.Response = SDIO_RESPONSE_SHORT; cmdInit.WaitForInterrupt = SDIO_WAIT_NO; cmdInit.CPSM = SDIO_CPSM_Enable; SDIO_SendCommand(&cmdInit);

    // 如果是命令7,8,12,那么需要等待一段时间来接收完响应 if (cmd == SD_CMD_SEND_IF_COND || cmd == SD_CMD_APP_CMD || cmd == SD_CMD_SD_SEND_OP_COND) { for (uint32_t i = 0; i < 0xFFFF; ++i); // 等待一段时间 }

    // 根据命令获取响应结果 if (cmdInit.Response != SDIO_RESPONSE_NO) { while (!(__HAL_SDIO_GET_FLAG(&hsdio, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT))); if (__HAL_SDIO_GET_FLAG(&hsdio, SDIO_FLAG_CTIMEOUT)) { __HAL_SDIO_CLEAR_FLAG(&hsdio, SDIO_FLAG_CTIMEOUT); return 0; } if (__HAL_SDIO_GET_FLAG(&hsdio, SDIO_FLAG_CMDREND)) { __HAL_SDIO_CLEAR_FLAG(&hsdio, SDIO_FLAG_CMDREND); responseVal = SDIO_GetResponse(SDIO_RESP1); if (response != NULL) { response[3] = (responseVal & 0xFF000000) >> 24; response[2] = (responseVal & 0x00FF0000) >> 16; response[1] = (responseVal & 0x0000FF00) >> 8; response[0] = (responseVal & 0x000000FF); } } }

    return 1; }

/**

  • 等待SD卡准备就绪

  • @return 成功或失败标志 */ int SD_WaitReady() { uint32_t response; uint64_t timeout = HAL_GetTick() + 500; // 等待500毫秒

    // 等待SD卡准备就绪 do { if (!SD_SendCommand(SD_CMD_SEND_STATUS, 0, (uint8_t *) &response)) { return 0; } } while ((response & 0xFF) != 0x00 && HAL_GetTick() < timeout);

    return 1; }

/**

  • 读取SD卡的块数据

  • @param blockNumber 要读取的块号

  • @param buffer 数据缓冲区

  • @return 成功或失败标志 */ int SD_ReadBlock(uint32_t blockNumber, uint8_t *buffer) { if (!SD_WaitReady()) { return 0; }

    // 配置SD卡数据传输配置 SDIO_DataInitTypeDef dataInit; dataInit.DataTimeOut = SD_DATATIMEOUT; dataInit.DataLength = 512; dataInit.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; dataInit.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; dataInit.TransferMode = SDIO_TRANSFER_MODE_BLOCK; dataInit.DPSM = SDIO_DPSM_Enable; SDIO_DataConfig(&dataInit);

    // 发送读取块命令 if (!SD_SendCommand(SD_CMD_READ_SINGLE_BLOCK, blockNumber * 512, NULL)) { return 0; }

    // 接收数据 HAL_SD_IO_ReadBlocks((uint32_t *) buffer, 512, 1);

    // 等待数据传输完成 while (!(__HAL_SDIO_GET_FLAG(&hsdio, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR))); if (__HAL_SDIO_GET_FLAG(&hsdio, SDIO_FLAG_DTIMEOUT)) { __HAL_SDIO_CLEAR_FLAG(&hsdio, SDIO_FLAG_DTIMEOUT); return 0; } if (__HAL_SDIO_GET_FLAG(&hsdio, SDIO_FLAG_DCRCFAIL)) { __HAL_SDIO_CLEAR_FLAG(&hsdio, SDIO_FLAG_DCRCFAIL); return 0; } if (__HAL_SDIO_GET_FLAG(&hsdio, SDIO_FLAG_RXOVERR)) { __HAL_SDIO_CLEAR_FLAG(&hsdio, SDIO_FLAG_RXOVERR); return 0; } if (__HAL_SDIO_GET_FLAG(&hsdio, SDIO_FLAG_STBITERR)) { __HAL_SDIO_CLEAR_FLAG(&hsdio, SDIO_FLAG_STBITERR); return 0; }

    return 1; }

/**

  • 写入SD卡的块数据

  • @param blockNumber 要写入的块号

  • @param buffer 数据缓冲区

  • @return 成功或失败标志 */ int SD_WriteBlock(uint32_t blockNumber, uint8_t *buffer) { if (!SD_WaitReady()) { return 0; }

    // 配置SD卡数据传输配置 SDIO_DataInitTypeDef dataInit; dataInit.DataTimeOut = SD_DATATIMEOUT; dataInit.DataLength = 512; dataInit.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; dataInit.TransferDir = SDIO_TRANSFER_DIR_TO_CARD; dataInit.TransferMode = SDIO_TRANSFER_MODE_BLOCK; dataInit.DPSM = SDIO_DPSM_Enable; SDIO_DataConfig(&dataInit);

    // 发送写入块命令 if (!SD_SendCommand(SD_CMD_WRITE_SINGLE_BLOCK, blockNumber * 512, NULL)) { return 0; }

    // 发送数据 HAL_SD_IO_WriteBlocks((uint32_t *) buffer, 512, 1);

    // 等待数据传输完成 while (!(__HAL_SDIO_GET_FLAG(&hsdio, SDIO_FLAG_TXUNDERR

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值