问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

STM32+HAL:SDIO+DMA模式读写SD卡详解

创作时间:
作者:
@小白创作中心

STM32+HAL:SDIO+DMA模式读写SD卡详解

引用
CSDN
1.
https://blog.csdn.net/m0_60372743/article/details/138328162

一、准备工作

有关CUBEMX的初始化配置,参见相关文档。

二、所用工具

  1. 芯片:STM32F407ZGT6
  2. IDE:MDK-Keil软件
  3. 库文件:STM32F4xxHAL库

三、实现功能

实现用SDIO+DMA读写SD卡内容

四、HAL库配置

  1. 开启SDIO
  • 模式配置为1bit,开启DMA传输,开启中断
  • Clock transition on which the bit capture is made(时钟跳变沿捕获数据配置):数据捕获边沿设置,可设置为上升沿/下降沿
  • SDIO Clock divider bypass(时钟分频器旁路使能):使能该参数时,SDIO_CLK=SDIOCLK;否则SDIO_CLK频率由时钟分频因子决定
  • SDIO Clock output enable when the bus is idle(空闲模式时钟输出使能):节能模式,此实验不使能
  • SDIO hardware flow control(硬件流控):设置是否使能SDIO的硬件流控,此处不使能
  • SDIOCLK clock divide factor(时钟分频因子):当不使能时钟分频器旁路时,SDIO_CLK=SDIOCLK / (2+时钟分频因子)
  1. 开启串口通信

至此,HAL库配置完毕

五、Keil填写代码

  1. SD.h
#ifndef __SD_H__
#define __SD_H__
#include "sdio.h"
#include "stdio.h"
void SDCard_TestRead(void);
void SDCard_TestWrite(void);
void SDCard_ShowInfo(void);
void SDCard_EraseBlocks(uint8_t BlockAddrStart,uint8_t BlockAddrEnd);
void SDCard_Write_DMA(uint8_t *TX, uint32_t BlockCount, uint32_t BlockAddr);
void SDCard_Read_DMA(uint8_t *RX,uint32_t BlockCount,uint32_t BlockAddr);
#endif
  1. SD.c

篇幅有限,仅提供SD.c核心代码

/**
  * @brief  SD卡DMA写入函数
  * @param  uint8_t *TX: 写入数据数组(若要存入负数,需提前加一个数值,典型值为127,此时数据范围为-127 ~ 128)
  * @param  BlockCount:  写入的总片数
  * @param  BlockAddr:   起始写入的片数
  */
void SDCard_Write_DMA(uint8_t *TX, uint32_t BlockCount, uint32_t BlockAddr)
{
    HAL_SD_WriteBlocks_DMA(&hsd, TX, BlockAddr, BlockCount);				//存入TX数组数据到sd卡
}
/**
  * @brief  SD卡DMA读取函数
  * @param  uint8_t *RX: 读取数据数组(若已存入负数,需在打印时减一个数值,典型值为127,此时数据范围为-127 ~ 128)
  * @param  BlockCount:  读取的总片数
  * @param  BlockAddr:   起始读取的片数
  */
void SDCard_Read_DMA(uint8_t *RX, uint32_t BlockCount, uint32_t BlockAddr)
{
    HAL_SD_ReadBlocks_DMA(&hsd, RX, BlockAddr, BlockCount);					//读取sd卡数据到RX数组
}
/**
  * @brief  SD卡擦除函数
  * @param  BlockAddrStart: 擦除开始块数
  * @param  BlockAddrEnd:   擦除结束块数
  */
void SDCard_EraseBlocks(uint8_t BlockAddrStart,uint8_t BlockAddrEnd)
{
    printf("\r\n*** Erasing blocks ***\r\n");
    if(HAL_SD_Erase(&hsd, BlockAddrStart, BlockAddrEnd)==HAL_OK)		//擦除数据
        printf("Erasing blocks,OK\r\n");
    else
        printf("Erasing blocks,fail\r\n");
    HAL_SD_CardStateTypeDef cardState=HAL_SD_GetCardState(&hsd);
    printf("GetCardState()= %d\r\n", cardState);						//打印当前sd卡数据状态
    while(cardState != HAL_SD_CARD_TRANSFER)
    {
        HAL_Delay(1);
        cardState=HAL_SD_GetCardState(&hsd);
    }
    printf("Blocks %d-%d is erased.\r\n",BlockAddrStart, BlockAddrEnd);
}
  1. main.c
uint8_t rx[BLOCKSIZE],tx[BLOCKSIZE];
/* USER CODE BEGIN 2 */
    printf("Hello World\r\n");
    HAL_Delay(500);
    SDCard_Write_DMA(tx,1,6);
    HAL_Delay(500);
    SDCard_Read_DMA(rx,1,6);
    HAL_Delay(500);
    SDCard_EraseBlocks(0,10);
  /* USER CODE END 2 */

六、巨人之肩

  • 【STM32+HAL】利用SDIO将大量数据存入SD卡,并根据需要读出
  • STM32CubeMX教程27 SDIO - 读写SD卡

七、源码提供

资源【STM32+HAL】SDIO+DMA模式读写SD卡

八、更多DMA应用

详见【STM32+HAL】DMA应用

九、结语

本文介绍了使用STM32F407ZGT6芯片通过MDK-Keil软件和STM32F4xxHAL库实现SD卡读写的具体步骤,包括HAL库配置、代码实现等,并提供了核心代码示例。希望对从事嵌入式系统开发的工程师有所帮助。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号