这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【STM32F769】SD卡驱动及其调试经验分享

共5条 1/1 1 跳转至

【STM32F769】SD卡驱动及其调试经验分享

工程师
2025-03-13 13:16:22   被打赏 32 分(兑奖)     打赏

【前言】

驱动MCU的SD卡,在日常的开发中,最为通用,用于数据的保存,固件升级等等都有很大的作用。这次我花了三天的时间对STM32F769-DISC1进行了驱动的学习,由于我是新手,官方的开发板提供了基于BSP的驱动示例,但是没有STM32CubeMX的工程,所以需要自行移植他的BSP里的驱动,或者使用STM32CubeMX进行配置驱动。STM32CubeMX配置出来,还是需要手工进行调整一些参数才行正常驱动,遇到了很多的坑,特此在这里记录并分享。

【软件环境】

1、操作系统 win11

2、配置工具:STM32CubeMX 6.13.0

3、代码编辑vscode 

【配置过程】

1、创建基于STM32F769NIHx的基本工程。

2、打开USART1,选择PA9、PA10为串口用的IO。其他使用默认配置。

3、打开RCC的外部晶振

4、打开SDMMC2,选择SD 4 bits Wide Bus。时钟分频为4分频。

image.png

5、确认GPIO与原理图一样。

6、添加DMA设置,添加RX、TX两个传输通道,添加后不用修改这里有参数,保持黙认即可。

image.png

7、使能DMA中断,三个中断都需要使能。

image.png

8、调整时钟配置,选择HSE为输入源,配置如下图:

image.png

这里一定要注间,SDMMC2为48MHz以下的时钟,我就是在这里没有配置好,在坑里爬了2天才找出原因。具体过程可以看我的另一篇帖子:

【STM32F769】调试SD驱动,由于其时钟配置不对引起的错误以及排查记录  https://forum.eepw.com.cn/thread/391294/1

9、打开工程选项,输入项目名称,选择Cmake工程,根据以后自己的应用调节栈大小。

image.png

10、生成工程,并使用vscode打开工程。

11、修改sdmmc.c的MX_SDMMC2_SD_Init函数,将最先的初始化需要修数据宽度为1b,要不会选成错误:

image.png

12、在usart.c的最后添加printf重定向代码:

image.png

14、在stm32f7xx_it.c的最后,添加dma回调函数,并声明全局变量传输标志:

/* USER CODE BEGIN 1 */
extern __IO uint32_t SDWriteStatus;
extern __IO uint32_t SDReadStatus ;
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(hsd);
  SDWriteStatus = 1;
}

void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
{

  UNUSED(hsd);
  SDReadStatus = 1;
}

void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd)
{

  UNUSED(hsd);
}

void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd)
{
  UNUSED(hsd);
}
/* USER CODE END 1 */

13、添加测试函数,首先打印卡的信息,然后进行读写测试,代码如下:

#include <stdio.h>
#include "sd_test1.h"
#include "main.h"
extern SD_HandleTypeDef hsd2;
#define BLOCK_START_ADDR 0 /* Block start address      */
/* BLOCKSIZE = 512 Bytes, defined in stm32f7xx_hal_sd.h */
#define NUM_OF_BLOCKS 50                                     /* Total number of blocks   */
#define BUFFER_WORDS_SIZE ((BLOCKSIZE * NUM_OF_BLOCKS) >> 2) /* Total data size in bytes */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint32_t aTxBuffer[BUFFER_WORDS_SIZE];
uint32_t aRxBuffer[BUFFER_WORDS_SIZE];
__IO uint32_t SDWriteStatus = 0, SDReadStatus = 0;

__IO uint32_t SdmmcTest = 0;
/* Private function prototypes -----------------------------------------------*/

static void Fill_Buffer(uint32_t *pBuffer, uint32_t uwBufferLenght, uint32_t uwOffset);
static uint8_t Buffercmp(uint32_t *pBuffer1, uint32_t *pBuffer2, uint16_t BufferLength);
/* Private functions ---------------------------------------------------------*/

uint8_t BSP_SD_GetCardState(void)
{
    return ((HAL_SD_GetCardState(&hsd2) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY);
}
void sd_test1(void)
{
    uint8_t SD_state = MSD_OK;

    HAL_SD_CardInfoTypeDef SDCardInfo;
    // 获取SD卡信息
    if (HAL_SD_GetCardInfo(&hsd2, &SDCardInfo) != HAL_OK)
    {
        // 获取信息失败处理
        printf("Failed to get SD card information!\n");
        while (1)
            ;
    }

    // 打印SD卡信息
    printf("SD Card Information:\n");
    printf("Card Type: %ld\n", SDCardInfo.CardType);
    printf("Card Version: %ld\n", SDCardInfo.CardVersion);
    printf("Card Capacity: %ld\n", SDCardInfo.BlockSize);
    printf("Card Block Size: %ld\n", SDCardInfo.BlockNbr);
    printf("Card Block Nbr: %ld\n", SDCardInfo.Class);
    printf("Card LogBlockSize: %ld\n", SDCardInfo.LogBlockSize);

    SD_state = HAL_SD_Erase(&hsd2, BLOCK_START_ADDR, (BLOCKSIZE * NUM_OF_BLOCKS)) ;

    while (BSP_SD_GetCardState() != SD_TRANSFER_OK)
    {
    }
    if (SD_state

【实验效果】

下载到开发板后,通过串口打印,日志如下:

image.png

【经验总结】

1、配置时钟需要特别注意 PLLQ要配置48MHz以下。

2、修改初始化为1Bit。

3、需要添加dma的中断回调函数来获取传输完成后的标志位。

总之,厉时3天多,终于把坑填上了。




关键词: STM32F769     经验     分享     SDMMC     SD         

专家
2025-03-13 21:49:14     打赏
2楼

感谢分享


院士
2025-03-13 23:06:53     打赏
3楼

真棒!

印象中,SDIO可以使用4线制,但要注意时序要求。


工程师
2025-03-14 07:04:04     打赏
4楼

我刚才的评论不能编辑,是我有点表述有问题。

SD在初始化时只能用一根DATA线进行初始化,初始化成功才能转换成4DATA来数据传输。


院士
2025-03-14 17:52:06     打赏
5楼

明白了。

谢谢大佬点拨



共5条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]
站长统计