一、准备工作
有关CUBEMX的初始化配置,参见我的另一篇blog:【STM32+HAL】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+时钟分频因子)
2、开启串口通信
至此,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
2、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);
}
3、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应用
九、结语
本人能力有限,代码未必是最优解,若有可改进之处望在评论区留言,采纳有赏~