stm32 sdio

发布时间 2023-06-07 20:30:43作者: y_blog

SDIO学习笔记

SDIO 简介

SDIO stm32驱动

stm32的SDIO驱动参考st官方的参考例程,其中详细说明了如何操作,官方的文档翻译如下:

1 如何使用此设备

它实现了一个高级通信层,用于从/向该存储器进行读写。所需的STM32硬件资源(SDIO和GPIO)在stm324xg_eval.h文件中定义,并在stm324xg_eval.c文件中声明的SD_LowLevel_Init()函数中进行初始化。
您可以通过适应硬件资源的定义和SD_LowLevel_Init()函数来轻松地将此驱动程序定制为任何其他开发板。

2 SD卡初始化和配置

要初始化SD卡,请使用SD_Init()函数。它初始化SD卡并将其置于待机状态(准备好数据传输)。此函数提供以下操作:

  1. 以400KHz的速度应用SD卡初始化过程,并检查SD卡类型(标准容量或高容量)。您可以通过调整stm324xg_eval.h文件中的“SDIO_INIT_CLK_DIV”定义来更改或适应此频率。 SD卡频率(SDIO_CK)计算如下:

\[SDIO\_CK = SDIOCLK /(SDIO\_INIT\_CLK\_DIV + 2) \]

在初始化模式下,并根据SD卡标准,请确保SDIO_CK频率不超过400KHz

  1. 获取SD CID和CSD数据。所有这些信息都由SDCardInfo结构管理。此结构还提供了预先计算的SD卡容量和块大小。

  2. 配置SD卡数据传输频率。默认情况下,卡传输频率设置为24MHz。您可以通过调整stm324xg_eval.h文件中的“SDIO_TRANSFER_CLK_DIV”定义来更改或适应此频率。 SD卡频率(SDIO_CK)计算如下:

\[SDIO\_CK = SDIOCLK /(SDIO\_INIT\_CLK\_DIV + 2) \]

在传输模式下,并根据SD卡标准,请确保SDIO_CK频率不超过25MHz,并且在高速模式切换时不超过50MHz。要能够使用高于24MHz的频率,您应该使用旁路模式下的SDIO外设。有关更多详细信息,请参阅相应的参考手册。

  1. 根据步骤2读取的地址选择相应的SD卡。

  2. 将SD卡配置为宽总线模式:4位数据。

3 SD卡读取操作

  1. 您可以使用SD_ReadBlock()SD_ReadMultiBlocks()函数读取SD卡。这些函数仅支持512字节的块长度。
  2. SD_ReadBlock()函数仅读取一个块(512字节)。此函数可以使用DMA控制器或使用轮询模式传输数据。要在DMA或轮询模式之间选择,请参阅stm324xg_eval_sdio_sd.h文件中的“SD_DMA_MODE”或“SD_POLLING_MODE”,并取消注释相应的行。默认情况下选择SD DMA模式
  3. SD_ReadMultiBlocks()函数仅读取多个块(512字节的倍数)。
  4. 任何读取操作都应跟随两个函数,以检查DMA控制器和SD卡状态。

SD_ReadWaitOperation():此函数确保DMA控制器已完成所有数据传输。
SD_GetStatus():检查SD卡是否已完成数据传输并准备好数据。

  1. DMA传输由SDIO数据结束中断完成。用户必须在SDIO_IRQHandler()中调用SD_ProcessIRQ()函数,在DMA2_Streamx_IRQHandler()中调用SD_ProcessDMAIRQ()函数。不要忘记使用NVIC控制器启用SDIO_IRQnDMA2_Stream3_IRQnDMA2_Stream6_IRQn中断。

3 SD卡写入操作

  1. 您可以使用SD_WriteBlock()和SD_WriteMultiBlocks()函数写入SD卡。这些函数仅支持512字节的块长度。
  2. SD_WriteBlock()函数仅写入一个块(512字节)。此函数可以使用DMA控制器或使用轮询模式传输数据。要在DMA或轮询模式之间选择,请参阅stm324xg_eval_sdio_sd.h文件中的“SD_DMA_MODE”或“SD_POLLING_MODE”,并取消注释相应的行。默认情况下选择SD DMA模式
  3. SD_WriteMultiBlocks()函数仅写入多个块(512字节的倍数)。
  4. 任何写入操作都应跟随两个函数,以检查DMA控制器和SD卡状态。

SD_ReadWaitOperation():此函数确保DMA控制器已完成所有数据传输。
SD_GetStatus():检查SD卡是否已完成数据传输并准备好数据。

  1. DMA传输由SDIO数据结束中断完成。用户必须在SDIO_IRQHandler()中调用SD_ProcessIRQ()函数,在DMA2_Streamx_IRQHandler()中调用SD_ProcessDMAIRQ()函数。不要忘记使用NVIC控制器启用SDIO_IRQnDMA2_Stream3_IRQnDMA2_Stream6_IRQn中断。

4 SD卡状态

  1. 您可以随时使用SD_GetStatus()函数检查SD卡状态并获取SD卡状态。此函数首先检查SD卡是否仍连接,然后获取内部SD卡传输状态。
  2. 您还可以使用SD_SendSDStatus()函数获取SD卡SD状态寄存器。

5 编程模型(选择DMA进行SDIO数据传输)

Status = SD_Init(); //如A节所述的初始化步骤

// SDIO中断使能
NVIC_InitStructure.NVIC_IRQChannel = SDIO_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// DMA2 STREAMx中断使能
NVIC_InitStructure.NVIC_IRQChannel = SD_SDIO_DMA_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_Init(&NVIC_InitStructure);

//如C节所述的写操作
Status = SD_WriteBlock(buffer, address, 512);
Status = SD_WaitWriteOperation();
while(SD_GetStatus() != SD_TRANSFER_OK);

Status = SD_WriteMultiBlocks(buffer, address, 512, NUMBEROFBLOCKS);
Status = SD_WaitWriteOperation();
while(SD_GetStatus() != SD_TRANSFER_OK);

//如B节所述的读操作
Status = SD_ReadBlock(buffer, address, 512);
Status = SD_WaitReadOperation();
while(SD_GetStatus() != SD_TRANSFER_OK);

Status = SD_ReadMultiBlocks(buffer, address, 512, NUMBEROFBLOCKS);
Status = SD_WaitReadOperation();
while(SD_GetStatus() != SD_TRANSFER_OK);

- 添加SDIO和DMA2 StreamX(3或6)IRQ处理程序:   
void SDIO_IRQHandler(void)
{
    SD_ProcessIRQ();  
}   
void SD_SDIO_DMA_IRQHANDLER(void)
{
    SD_ProcessDMAIRQ();  
}

6 编程模型(选择轮询进行SDIO数据传输)

//仅管理SD卡单块操作。   
Status = SD_Init(); //如A节所述的初始化步骤

//如C节所述的写操作
Status = SD_WriteBlock(buffer, address, 512);

//如B节所述的读操作
Status = SD_ReadBlock(buffer, address, 512);

STM32 SDIO引脚分配