5.24 SDIO 使用说明

SDIO 是 N32H49x 标准外设库中的 SD 卡主机接口,支持 SD 存储卡、SD I/O 卡与 MMC 4.2 卡,具备命令通道、数据通道与数据 FIFO,可配合 DMA 完成块读写与擦除。本章介绍驱动的相关文件、66 个公开函数,以及示例 SD_Card。关于 SDIO 总线协议、命令与响应格式、命令与数据状态机,以及寄存器位定义,请结合用户手册“SDIO接口(SDIO)”一章阅读。

5.24.1 相关文件

相对路径 用途
firmware/n32h49x_std_periph_driver/inc/n32h49x_sdio.h 定义 SDIO_InitType、SDIO_CmdInitType、SDIO_DataInitType 结构体与电源、时钟分频、总线宽度、命令响应、数据块长度等宏;
声明 66 个公开函数,按复位与初始化、中断与 DMA、命令发送与响应、数据通道配置、块读写、擦除、卡识别,以及响应错误检查分组
firmware/n32h49x_std_periph_driver/src/n32h49x_sdio.c 实现 66 个函数:寄存器复位与初始化、电源与时钟控制、命令发送与响应读取、数据通道配置、FIFO 读写、块读写与擦除命令,以及各响应类型的错误检查
projects/n32h49x_EVAL/examples/SDIO/ SDIO 示例根目录,仅包含一个示例 SD_Card
projects/n32h49x_EVAL/examples/SDIO/SD_Card/ 该示例的工程构成:inc/、src/、readme.txt、MDK-ARM/、EWARM/
projects/n32h49x_EVAL/bsp/ 示例引用的板级支持文件:日志打印接口 log.c 与 log.h、延时接口 delay.c,以及评估板的引脚与时钟定义

5.24.2 API 参考

搜索 API共 66 个函数

以下 66 个公开函数按 n32h49x_sdio.h 的声明顺序列出,分为 13 组;每个函数给出一句功能摘要,并附 n32h49x_sdio.c 中函数正上方的原始注释。

复位与初始化

SDIO_DeInit, SDIO_Init, SDIO_InitStruct, SDIO_EnableClock, SDIO_SetPower, SDIO_GetPower

中断与 DMA

SDIO_ConfigInt, SDIO_DMACmd

命令发送与响应

SDIO_SendCmd, SDIO_InitCmdStruct, SDIO_GetCmdResp, SDIO_GetResp

数据通道配置

SDIO_ConfigData, SDIO_InitDataStruct, SDIO_GetDataCountValue, SDIO_ReadData, SDIO_WriteData, SDIO_GetFifoCounter

读等待

SDIO_EnableReadWait, SDIO_EnableReadWaitMode, SDIO_StartReadWait, SDIO_StopReadWait

SD I/O 模式与命令完成

SDIO_EnableSdioOperation, SDIO_EnableSendSdioSuspend, SDIO_EnableCommandCompletion

标志与中断状态

SDIO_GetFlag, SDIO_ClrFlag, SDIO_GetIntStatus

基础命令

SDIO_CmdShortResponse1, SDIO_CmdShortResponse3, SDIO_CmdLongResponse2, SDIO_CmdBlockLength, SDIO_CmdBlockCount

块读写命令

SDIO_CmdReadSingleBlock, SDIO_CmdReadMultiBlock, SDIO_CmdWriteSingleBlock, SDIO_CmdWriteMultiBlock

擦除命令

SDIO_CmdSDEraseStartAdd, SDIO_CmdSDEraseEndAdd, SDIO_CmdEraseStartAdd, SDIO_CmdEraseEndAdd, SDIO_CmdErase

卡识别命令

SDIO_CmdLockUnlock, SDIO_CmdStopTransfer, SDIO_CmdSelDesel, SDIO_CmdGoIdleState, SDIO_CmdOperCond, SDIO_CmdAppCommand, SDIO_CmdAppOperCommand, SDIO_CmdBusWidth, SDIO_CmdSendSCR, SDIO_CmdAllSendCID, SDIO_CmdSendCID, SDIO_CmdSendCSD

地址与状态命令

SDIO_CmdSetRelAdd, SDIO_CmdSetRelAddMmc, SDIO_CmdSendStatus, SDIO_CmdStatusRegister, SDIO_CmdOpCondition, SDIO_CmdSwitch, SDIO_CmdSendEXTCSD

响应错误检查

SDIO_GetCmdResp1, SDIO_GetCmdResp2, SDIO_GetCmdResp3, SDIO_GetCmdResp6, SDIO_GetCmdResp7

void SDIO_DeInit(void)将 SDIO 外设寄存器复位为默认值。
源码注释
name   SDIO_DeInit.
fun    Reset the SDIO peripheral registers to their default reset values.
param  none
return none
void SDIO_Init(SDIO_InitType* InitStruct)按 InitStruct 中的参数初始化 SDIO 外设。
源码注释
name   SDIO_Init.
fun    Initializes the SDIO peripheral according to the specified
       parameters in the InitStruct.
param  InitStruct pointer to a SDIO_InitType structure.
       The input parameters must be the following values:
          - ClkEdge:
               - SDIO_CLK_EDGE_RISING
               - SDIO_CLK_EDGE_FALLING
          - ClkBypass:
               - SDIO_CLK_BYPASS_DISABLE
               - SDIO_CLK_BYPASS_ENABLE
          - ClkPwrSave:
               - SDIO_CLK_POWER_SAVE_DISABLE
               - SDIO_CLK_POWER_SAVE_ENABLE
          - BusWidth:
               - SDIO_BUS_WIDTH_1B
               - SDIO_BUS_WIDTH_4B
               - SDIO_BUS_WIDTH_8B
          - HardwareClkCtrl:
               - SDIO_HARDWARE_CLKCTRL_DISABLE
               - SDIO_HARDWARE_CLKCTRL_ENABLE
          - ClkDiv: Must be a value between 0x00 and 0x1FF.
return none
void SDIO_InitStruct(SDIO_InitType* InitStruct)将 InitStruct 的各个成员填充为默认值。
源码注释
name   SDIO_InitStruct.
fun    Fills each InitStruct member with its default value.
param  InitStruct pointer to an SDIO_InitType structure which will be initialized.
return none
void SDIO_EnableClock(FunctionalState Cmd)使能或关闭 SDIO 时钟。
源码注释
name   SDIO_EnableClock.
fun    Enables or disables the SDIO Clock.
param  Cmd new state of the SDIO Clock.
           This parameter must be one of the following values:
               - ENABLE
               - DISABLE
return none
void SDIO_SetPower(uint32_t PowerState)设置控制器的电源状态。
源码注释
name   SDIO_SetPower.
fun    Sets the power status of the controller.
param  PowerState new state of the Power state.
           This parameter must be one of the following values:
               - SDIO_POWER_CTRL_OFF
               - SDIO_POWER_CTRL_ON
return none
uint32_t SDIO_GetPower(void)获取控制器的电源状态。
源码注释
name   SDIO_GetPower.
fun    Gets the power status of the controller.
param  none
return Current Power status,the value can be:
           - SDIO_POWER_CTRL_OFF
           - SDIO_POWER_CTRL_UP
           - SDIO_POWER_CTRL_ON
void SDIO_ConfigInt(uint32_t Int, FunctionalState Cmd)使能或关闭 SDIO 中断。
源码注释
name   SDIO_ConfigInt.
fun    Enables or disables the SDIO interrupts.
param  Int specifies the SDIO interrupt sources to be enabled or disabled.
           This parameter must be a value or combination of the following values:
               - SDIO_INT_CCRCERR
               - SDIO_INT_DCRCERR
               - SDIO_INT_CMDTIMEOUT
               - SDIO_INT_DATTIMEOUT
               - SDIO_INT_TXURERR
               - SDIO_INT_RXORERR
               - SDIO_INT_CMDRESPRECV
               - SDIO_INT_CMDSEND
               - SDIO_INT_DATEND
               - SDIO_INT_SBERR
               - SDIO_INT_DATBLKEND
               - SDIO_INT_CMDRUN
               - SDIO_INT_TXRUN
               - SDIO_INT_RXRUN
               - SDIO_INT_TFIFOE
               - SDIO_INT_TFIFOHE
               - SDIO_INT_TFIFOF
               - SDIO_INT_TDATVALID
               - SDIO_INT_RFIFOE
               - SDIO_INT_RFIFOHF
               - SDIO_INT_RFIFOF
               - SDIO_INT_RDATVALID
               - SDIO_INT_SDIOINT
param  Cmd new state of the specified SDIO interrupts.Must be one of one of the following values:
               - ENABLE
               - DISABLE
return none
void SDIO_DMACmd(FunctionalState Cmd)使能或关闭 SDIO 的 DMA 请求。
源码注释
name   SDIO_DMACmd.
fun    Enables or disables the SDIO DMA request.
param  Cmd new state of the SDIO DMA request.
           This parameter must be one of the following values:
               - ENABLE
               - DISABLE
return none
void SDIO_SendCmd(SDIO_CmdInitType* CmdInitStruct)按 CmdInitStruct 中的参数初始化 SDIO 命令并发送该命令。
源码注释
name   SDIO_SendCmd.
fun    Initializes the SDIO Command according to the specified
       parameters in the CmdInitStruct and send the command.
param  CmdInitStruct pointer to a SDIO_CmdInitType structure.
       The input parameters must be the following values:
          - CmdArgument: Optional SDIO command argument.
          - CmdIndex: SDIO command index, must be lower than 0x40.
          - ResponseType:
               - SDIO_RESP_NO
               - SDIO_RESP_SHORT
               - SDIO_RESP_LONG
          - WaitType:
               - SDIO_WAIT_NO
               - SDIO_WAIT_INT
               - SDIO_WAIT_PEND
          - CPSMConfig:
               - SDIO_CPSM_DISABLE
               - SDIO_CPSM_ENABLE
return none
void SDIO_InitCmdStruct(SDIO_CmdInitType* CmdInitStruct)将 CmdInitStruct 的各个成员填充为默认值。
源码注释
name   SDIO_InitCmdStruct.
fun    Fills each CmdInitStruct member with its default value.
param  CmdInitStruct pointer to a SDIO_CmdInitType structure.
return none
uint8_t SDIO_GetCmdResp(void)返回最后收到响应的命令索引。
源码注释
name   SDIO_GetCmdResp.
fun    Returns command index of last command for which response received.
param  none
return Command index of the last command response received
uint32_t SDIO_GetResp(uint32_t SDIO_RESP)返回上一条命令从卡收到的响应。
源码注释
name   SDIO_GetResp.
fun    Returns response received from the card for the last command.
param  SDIO_RESP Specifies the SDIO response register.
       This parameter must be one of the following values:
           - SDIO_RESPONSE_1
           - SDIO_RESPONSE_2
           - SDIO_RESPONSE_3
           - SDIO_RESPONSE_4
return The Corresponding response register value.
void SDIO_ConfigData(SDIO_DataInitType* DataInitStruct)按 DataInitStruct 中的参数初始化 SDIO 数据通道。
源码注释
name   SDIO_ConfigData.
fun    Initializes the SDIO data path according to the specified
       parameters in the DataInitStruct.
param  DataInitStruct pointer to a SDIO_DataInitType structure.
       The input parameters must be the following values:
          - DatTimeout: data timeout period.
          - DatLen: Number of data bytes to be transferred,
                   must be a value between 0x0 and 0x01FFFFFF
          - DatBlkSize:
               - SDIO_DATBLK_SIZE_1B
               - SDIO_DATBLK_SIZE_2B
               - SDIO_DATBLK_SIZE_4B
               - SDIO_DATBLK_SIZE_8B
               - SDIO_DATBLK_SIZE_16B
               - SDIO_DATBLK_SIZE_32B
               - SDIO_DATBLK_SIZE_64B
               - SDIO_DATBLK_SIZE_128B
               - SDIO_DATBLK_SIZE_256B
               - SDIO_DATBLK_SIZE_512B
               - SDIO_DATBLK_SIZE_1024B
               - SDIO_DATBLK_SIZE_2048B
               - SDIO_DATBLK_SIZE_4096B
               - SDIO_DATBLK_SIZE_8192B
               - SDIO_DATBLK_SIZE_16384B
          - TransferDirection:
               - SDIO_TRANSDIR_TOCARD
               - SDIO_TRANSDIR_TOSDIO
          - TransferMode:
               - SDIO_TRANSMODE_BLOCK
               - SDIO_TRANSMODE_STREAM
          - DPSMConfig:
               - SDIO_DPSM_DISABLE
               - SDIO_DPSM_ENABLE
return none
void SDIO_InitDataStruct(SDIO_DataInitType* DataInitStruct)将 DataInitStruct 的各个成员填充为默认值。
源码注释
name   SDIO_InitDataStruct.
fun    Fills each DataInitStruct member with its default value.
param  DataInitStruct pointer to a SDIO_DataInitType structure.
return none
uint32_t SDIO_GetDataCountValue(void)返回剩余待传输的数据字节数。
源码注释
name   SDIO_GetDataCountValue.
fun    Returns number of remaining data bytes to be transferred.
param  none
return Number of remaining data bytes to be transferred.
uint32_t SDIO_ReadData(void)从接收 DATFIFO 读取一个字。
源码注释
name   SDIO_ReadData.
fun    Read one data word from Rx DATFIFO.
param  none
return Data received.
void SDIO_WriteData(uint32_t Data)向发送 DATFIFO 写入一个字。
源码注释
name   SDIO_WriteData.
fun    Write one data word to Tx DATFIFO.
param  Data 32-bit data word to write.
return none
uint32_t SDIO_GetFifoCounter(void)返回 DATFIFO 中待写入或待读取的字数。
源码注释
name   SDIO_GetFifoCounter.
fun    Returns the number of words left to be written to or read from DATFIFO.
param  none
return Remaining number of words in the FIFO.
void SDIO_EnableReadWait(FunctionalState Cmd)使能 SD I/O 读等待操作。
源码注释
name   SDIO_EnableReadWait.
fun    Enable the SD I/O Read Wait operation.
param  Cmd new state of the read wait operation.
           This parameter must be one of the following values:
               - ENABLE
               - DISABLE
return none
void SDIO_EnableReadWaitMode(uint32_t ReadWaitMode)设置插入读等待间隔的两种方式之一。
源码注释
name   SDIO_EnableSdioReadWaitMode.
fun    Sets one of the two options of inserting read wait interval.
param  ReadWaitMode SD I/O Read Wait operation mode.
           This parameter must be one of the following values:
               - SDIO_RDWAIT_MODE_CLK
               - SDIO_RDWAIT_MODE_DAT2
return none
void SDIO_StartReadWait(void)在 RWAITEN 置位时启动 SD I/O 读等待操作。
源码注释
name   SDIO_StartReadWait.
fun    Start the SD I/O Read Wait operation when RWAITEN bit is set.
param  none
return none
void SDIO_StopReadWait(void)在 RWAITEN 置位时停止 SD I/O 读等待操作。
源码注释
name   SDIO_StopReadWait.
fun    Stop the SD I/O Read Wait operation when RWAITEN bit is set.
param  none
return none
void SDIO_EnableSdioOperation(FunctionalState Cmd)使能 SD I/O 模式操作。
源码注释
name   SDIO_EnableSdioOperation.
fun    Enables the SD I/O Mode Operation.
param  Cmd new state of the SD I/O Mode Operation.
           This parameter must be one of the following values:
               - ENABLE
               - DISABLE
return none
void SDIO_EnableSendSdioSuspend(FunctionalState Cmd)使能 SD I/O 模式挂起命令的发送。
源码注释
name   SDIO_EnableSendSdioSuspend.
fun    Enables the SD I/O Mode suspend command sending.
param  Cmd new state of the SD I/O Mode suspend command sending.
           This parameter must be one of the following values:
               - ENABLE
               - DISABLE
return none
void SDIO_EnableCommandCompletion(FunctionalState Cmd)使能命令完成信号。
源码注释
name   SDIO_EnableCommandCompletion.
fun    Enables the command completion signal.
param  Cmd new state of the command completion signal.
           This parameter must be one of the following values:
               - ENABLE
               - DISABLE
return none
FlagStatus SDIO_GetFlag(uint32_t Flag)检查指定的 SDIO 标志是否置位。
源码注释
name   SDIO_GetFlag.
fun    Checks whether the specified SDIO flag is set or not.
param  Flag specifies the flag to check.
           This parameter must be one of the following values:
               - SDIO_FLAG_CCRCERR
               - SDIO_FLAG_DCRCERR
               - SDIO_FLAG_CMDTIMEOUT
               - SDIO_FLAG_DATTIMEOUT
               - SDIO_FLAG_TXURERR
               - SDIO_FLAG_RXORERR
               - SDIO_FLAG_CMDRESPRECV
               - SDIO_FLAG_CMDSEND
               - SDIO_FLAG_DATEND
               - SDIO_FLAG_SBERR
               - SDIO_FLAG_DATBLKEND
               - SDIO_FLAG_CMDRUN
               - SDIO_FLAG_TXRUN
               - SDIO_FLAG_RXRUN
               - SDIO_FLAG_TFIFOE
               - SDIO_FLAG_TFIFOHE
               - SDIO_FLAG_TFIFOF
               - SDIO_FLAG_TDATVALID
               - SDIO_FLAG_RFIFOE
               - SDIO_FLAG_RFIFOHF
               - SDIO_FLAG_RFIFOF
               - SDIO_FLAG_RDATVALID
               - SDIO_FLAG_SDIOINT
return FlagStatus:
           - SET
           - RESET
void SDIO_ClrFlag(uint32_t FlagClr)清除 SDIO 的待处理标志。
源码注释
name   SDIO_ClrFlag.
fun    Clears the SDIO's pending flags.
param  FlagClr specifies the flag to clear.
           This parameter must be one of the following values:
               - SDIO_FLAG_CCRCERR
               - SDIO_FLAG_DCRCERR
               - SDIO_FLAG_CMDTIMEOUT
               - SDIO_FLAG_DATTIMEOUT
               - SDIO_FLAG_TXURERR
               - SDIO_FLAG_RXORERR
               - SDIO_FLAG_CMDRESPRECV
               - SDIO_FLAG_CMDSEND
               - SDIO_FLAG_DATEND
               - SDIO_FLAG_SBERR
               - SDIO_FLAG_DATBLKEND
               - SDIO_FLAG_SDIOINT
return none
INTStatus SDIO_GetIntStatus(uint32_t Int)检查指定的 SDIO 中断是否发生。
源码注释
name   SDIO_GetIntStatus.
fun    Checks whether the specified SDIO interrupt has occurred or not.
param  Int specifies the SDIO interrupt source to check.
           This parameter must be one of the following values:
               - SDIO_INT_CCRCERR
               - SDIO_INT_DCRCERR
               - SDIO_INT_CMDTIMEOUT
               - SDIO_INT_DATTIMEOUT
               - SDIO_INT_TXURERR
               - SDIO_INT_RXORERR
               - SDIO_INT_CMDRESPRECV
               - SDIO_INT_CMDSEND
               - SDIO_INT_DATEND
               - SDIO_INT_SBERR
               - SDIO_INT_DATBLKEND
               - SDIO_INT_CMDRUN
               - SDIO_INT_TXRUN
               - SDIO_INT_RXRUN
               - SDIO_INT_TFIFOE
               - SDIO_INT_TFIFOHE
               - SDIO_INT_TFIFOF
               - SDIO_INT_TDATVALID
               - SDIO_INT_RFIFOE
               - SDIO_INT_RFIFOHF
               - SDIO_INT_RFIFOF
               - SDIO_INT_RDATVALID
               - SDIO_INT_SDIOINT
return INTStatus:
           - SET
           - RESET
uint32_t SDIO_CmdShortResponse1(uint8_t Cmd, uint32_t Arg, uint32_t timeout)带参数发送命令并按超时检查 R1 响应。
源码注释
name   SDIO_CmdShortResponse1.
fun    Send command with argument and check R1 response with timeout.
param  Cmd specifies the command index to be sent.
param  Arg specifies the command argument.
param  timeout timeout value for response, can not be 0.
return SDIO error state
uint32_t SDIO_CmdShortResponse3(uint8_t Cmd, uint32_t Arg)带参数发送命令并检查 R3 响应。
源码注释
name   SDIO_CmdShortResponse3.
fun    Send command with argument and check R3 response.
param  Cmd specifies the command index to be sent.
param  Arg specifies the command argument.
return SDIO error state
uint32_t SDIO_CmdLongResponse2(uint8_t Cmd, uint32_t Arg)带参数发送命令并检查 R2 响应。
源码注释
name   SDIO_CmdLongResponse2.
fun    Send command with argument and check the R2 response.
param  Cmd specifies the command index to be sent.
param  Arg specifies the command argument.
return SDIO error state
uint32_t SDIO_CmdBlockLength(uint32_t BlockSize)发送设置数据块长度命令并检查响应。
源码注释
name   SDIO_CmdBlockLength.
fun    Send the Data Block Length command and check the response
param  BlockSize specifies the SDIO data block length.
return SDIO error state
uint32_t SDIO_CmdBlockCount(uint32_t BlockCnt)发送设置数据块数量命令并检查响应。
源码注释
name   SDIO_CmdBlockCount.
fun    Send the Set Data Block Count command and check the response
param  BlockCnt specifies the SDIO block count.
return SDIO error state
uint32_t SDIO_CmdReadSingleBlock(uint32_t ReadAdd)发送读单块命令并检查响应。
源码注释
name   SDIO_CmdReadSingleBlock.
fun    Send the Read Single Block command and check the response
param  ReadAdd specifies the start address for reading.
return SDIO error state
uint32_t SDIO_CmdReadMultiBlock(uint32_t ReadAdd)发送读多块命令并检查响应。
源码注释
name   SDIO_CmdReadMultiBlock.
fun    Send the Read Multi Block command and check the response
param  ReadAdd specifies the start address for reading.
return SDIO error state
uint32_t SDIO_CmdWriteSingleBlock(uint32_t WriteAdd)发送写单块命令并检查响应。
源码注释
name   SDIO_CmdWriteSingleBlock.
fun    Send the Write Single Block command and check the response
param  WriteAdd specifies the start address for writing.
return SDIO error state
uint32_t SDIO_CmdWriteMultiBlock(uint32_t WriteAdd)发送写多块命令并检查响应。
源码注释
name   SDIO_CmdWriteMultiBlock.
fun    Send the Write Multi Block command and check the response
param  WriteAdd specifies the start address for writing.
return SDIO error state
uint32_t SDIO_CmdSDEraseStartAdd(uint32_t StartAdd)发送 SD 起始地址擦除命令并检查响应。
源码注释
name   SDIO_CmdSDEraseStartAdd.
fun    Send the Start Address Erase command for SD and check the response
param  StartAdd specifies the start address for erasing.
return SDIO error state
uint32_t SDIO_CmdSDEraseEndAdd(uint32_t EndAdd)发送 SD 结束地址擦除命令并检查响应。
源码注释
name   SDIO_CmdSDEraseEndAdd.
fun    Send the End Address Erase command for SD and check the response
param  EndAdd specifies the end address for erasing.
return SDIO error state
uint32_t SDIO_CmdEraseStartAdd(uint32_t StartAdd)发送起始地址擦除命令并检查响应。
源码注释
name   SDIO_CmdEraseStartAdd.
fun    Send the Start Address Erase command and check the response
param  StartAdd specifies the start address for erasing.
return SDIO error state
uint32_t SDIO_CmdEraseEndAdd(uint32_t EndAdd)发送结束地址擦除命令并检查响应。
源码注释
name   SDIO_CmdEraseEndAdd.
fun    Send the End Address Erase command and check the response
param  StartAdd specifies the start address for erasing.
return SDIO error state
uint32_t SDIO_CmdErase(void)发送擦除命令并检查响应。
源码注释
name   SDIO_CmdErase.
fun    Send the Erase command and check the response
param  none
return SDIO error state
uint32_t SDIO_CmdLockUnlock(uint32_t Arg)发送上锁或解锁命令并检查响应。
源码注释
name   SDIO_CmdLockUnlock.
fun    Send the lock/unlock command and check the response
param  none
return SDIO error state
uint32_t SDIO_CmdStopTransfer(void)发送停止传输命令并检查响应。
源码注释
name   SDIO_CmdStopTransfer.
fun    Send the Stop Transfer command and check the response.
param  none
return SDIO error state
uint32_t SDIO_CmdSelDesel(uint16_t RCA)发送选择或取消选择命令并检查响应。
源码注释
name   SDIO_CmdSelDesel.
fun    Send the Select Deselect command and check the response.
param  RCA: Address of the card to be selected
return SDIO error state
uint32_t SDIO_CmdGoIdleState(void)发送进入空闲状态命令并检查响应。
源码注释
name   SDIO_CmdGoIdleState.
fun    Send the Go Idle State command and check the response.
param  none
return SDIO error state
uint32_t SDIO_CmdOperCond(void)发送工作条件命令并检查响应。
源码注释
name   SDIO_CmdOperCond.
fun    Send the Operating Condition command and check the response.
param  none
return SDIO error state
uint32_t SDIO_CmdAppCommand(uint32_t Arg)发送应用命令,用来说明下一条是应用专用命令而非标准命令,并检查响应。
源码注释
name   SDIO_CmdAppCommand.
fun    Send the Application command to verify that that the next command
       is an application specific com-mand rather than a standard command
       and check the response.
param  Arg: Command Argument
return SDIO error state
uint32_t SDIO_CmdAppOperCommand(uint32_t Arg)发送命令请求被访问的卡返回其工作条件寄存器(OCR)。
源码注释
name   SDIO_CmdAppOperCommand.
fun    Send the command asking the accessed card to send its operating
       condition register (OCR)
param  Arg: Command Argument
return SDIO error state
uint32_t SDIO_CmdBusWidth(uint32_t BusWidth)发送总线宽度命令并检查响应。
源码注释
name   SDIO_CmdBusWidth.
fun    Send the Bus Width command and check the response.
param  BusWidth: Bus width
return SDIO error state
uint32_t SDIO_CmdSendSCR(void)发送获取 SCR 命令并检查响应。
源码注释
name   SDIO_CmdSendSCR.
fun    Send the Send SCR command and check the response.
param  none
return SDIO error state
uint32_t SDIO_CmdAllSendCID(void)发送广播获取 CID 命令并检查响应。
源码注释
name   SDIO_CmdAllSendCID.
fun    Send the Send all CID command and check the response.
param  none
return SDIO error state
uint32_t SDIO_CmdSendCID(uint16_t RCA)发送获取 CID 命令并检查响应。
源码注释
name   SDIO_CmdSendCID.
fun    Send the Send CID command and check the response.
param  RCA: Card RCA
return SDIO error state
uint32_t SDIO_CmdSendCSD(uint16_t RCA)发送获取 CSD 命令并检查响应。
源码注释
name   SDIO_CmdSendCSD.
fun    Send the Send CSD command and check the response.
param  RCA: Card RCA
return SDIO error state
uint32_t SDIO_CmdSetRelAdd(uint16_t *pRCA)发送设置相对地址命令。
源码注释
name   SDIO_CmdSetRelAdd.
fun    Send the Set Relative Address command.
param  pRCA: pointer to the Card RCA
return SDIO error state
uint32_t SDIO_CmdSetRelAddMmc(uint16_t RCA)向 MMC 卡(非 SD 卡)发送设置相对地址命令。
源码注释
name   SDIO_CmdSetRelAddMmc.
fun    Send the Set Relative Address command to MMC card (not SD card).
param  RCA: Card RCA
return SDIO error state
uint32_t SDIO_CmdSendStatus(uint32_t Arg)发送状态命令并检查响应。
源码注释
name   SDIO_CmdSendStatus.
fun    Send the Status command and check the response.
param  Arg: command argument
return SDIO error state
uint32_t SDIO_CmdStatusRegister(void)发送状态寄存器命令并检查响应。
源码注释
name   SDIO_CmdStatusRegister.
fun     Send the Status register command and check the response.
param  none
return SDIO error state
uint32_t SDIO_CmdOpCondition(uint32_t Arg)发送主机容量支持信息,并通过 SEND_OP_COND 命令启动卡初始化过程。
源码注释
name   SDIO_CmdOpCondition.
fun    Sends host capacity support information and activates the card's
       initialization process by send SDMMC_CMD_SEND_OP_COND command.
param  Arg: command argument
return SDIO error state
uint32_t SDIO_CmdSwitch(uint32_t Arg)查询可切换功能并切换卡功能,对应 HS_SWITCH 命令。
源码注释
name   SDIO_CmdSwitch.
fun    Checks switchable function and switch card function. SDMMC_CMD_HS_SWITCH command
param  Arg: command argument
return SDIO error state
uint32_t SDIO_CmdSendEXTCSD(uint32_t Arg)发送获取 EXT_CSD 命令并检查响应。
源码注释
name   SDIO_CmdSendEXTCSD.
fun    Send the Send EXT_CSD command and check the response.
param  Arg: command argument
return SDIO error state
uint32_t SDIO_GetCmdResp1(uint8_t Cmd, uint32_t Timeout)检查 R1 响应的错误状态。
源码注释
name   SDIO_GetCmdResp1.
fun    Checks for error conditions for R1 response.
param  Cmd: The sent command index
param  Timeout: timeout value, can not be 0.
return SDIO error state
uint32_t SDIO_GetCmdResp2(void)检查 R2(CID 或 CSD)响应的错误状态。
源码注释
name   SDIO_GetCmdResp2.
fun    Checks for error conditions for R2 (CID or CSD) response.
param  none
return SDIO error state
uint32_t SDIO_GetCmdResp3(void)检查 R3(OCR)响应的错误状态。
源码注释
name   SDIO_GetCmdResp3.
fun    Checks for error conditions for R3 (OCR) response.
param  none
return SDIO error state
uint32_t SDIO_GetCmdResp6(uint8_t Cmd, uint16_t *pRCA)检查 R6(RCA)响应的错误状态。
源码注释
name   SDIO_GetCmdResp6
fun    Checks for error conditions for R6 (RCA) response.
param  Cmd: The sent command index
param  pRCA: Pointer to the variable that will contain the SD card relative address RCA
return SDIO error state
uint32_t SDIO_GetCmdResp7(void)检查 R7 响应的错误状态。
源码注释
name   SDIO_GetCmdResp7
fun    Checks for error conditions for R7 response.
param  none
return SDIO error state

5.24.3 Demo 示例说明

本节覆盖 SDIO 的唯一示例 SD_Card,它通过 SDIO 主机接口对板载 TF 卡完成一次读、擦、写测试并核验数据。

5.24.3.1 SD_Card SD 卡读写擦测试

工程目录: projects/n32h49x_EVAL/examples/SDIO/SD_Card/

初始化 SDIO 引脚与外设→上电并识别 TF 卡→切换到传输时钟与 4 位总线→读取指定块并打印数据→擦除后再写入相同数据→再读回逐字节比较→打印测试结果

项目 源码解读
功能 通过 SDIO 主机接口对板载 TF 卡执行一次完整的读、擦、写测试;
按键触发后先读取起始 4 个数据块,再擦除该区域并写入新的测试数据,最后读回逐字节比较。
源码组成 src/main.c:主循环、按键与 LED 处理、卡信息打印和缓冲区比较;
src/sdcard.c 与 inc/sdcard.h:SDIO 端口初始化、卡上电与识别、块读写、擦除和 DMA 通道配置;
inc/main.h:测试地址、块数、DMA 通道与 LED、按键定义;
readme.txt:功能、环境与使用说明;
MDK-ARM/ 与 EWARM/:Keil 与 IAR 工程。
关键配置 SDIO 主机接口,SDIOCLK 为 120 MHz(HCLK/2),初始化分频 298、传输分频 4;
CLK 为 PC12、CMD 为 PD2、D0 为 PB4、D1 为 PB0、D2 为 PC10、D3 为 PC11,均配为复用推挽;
时钟上升沿有效、关闭硬件流控、总线宽度 4 位;
读写走 DMA1 通道 1,测试起始地址为 0、块数为 4、块大小为 512 字节;
按键为 PA0,指示 LED 为 PA3。
系统时钟为 240 MHz,打印串口为 PA9,波特率 115200。
程序与数据路径 main 初始化日志、LED 与按键后进入循环;
按键按下并释放后调用 SD_Init 初始化卡,随后 SD_ShowCardInfo 打印卡信息;
依次调用 SD_ReadBlocks、SD_Erase、SD_WriteBlocks 完成读、擦、写,再读回比较;
每一步之后都等待 SD_GetCardState 回到传输状态。
主要 API SD_Init, SD_GetCardState, SD_ReadBlocks, SD_WriteBlocks, SD_Erase, SDIO_DMACmd
验证方法 在卡座中插入 TF 卡,编译下载并复位开发板;
按一下 PA0 触发一轮测试,串口先打印 demo 起始信息与卡信息,再打印读、擦、写各步骤的结果,最后打印 SD/MMC Card test OK!。
使用提示 测试前必须外接 TF 卡座并插入 TF 卡;
读写擦会破坏起始 4 个数据块,测试前请确认该区域没有有用数据;
工具链为 KEIL MDK-ARM 5.34 与 IAR EWARM 8.50.1。
核心代码解读与移植

示例在按键触发后用 SDIO 主机接口对 TF 卡做一轮读、擦、写:先按块读回数据,再擦除该区域并写入新的测试数据,最后读回比较。

数据路径: main → SD_Init 配置 SDIO 外设并上电识别卡 → SD_ShowCardInfo 打印卡信息 → SD_ReadBlocks 用 DMA 读回数据 → SD_Erase 擦除区域 → SD_WriteBlocks 写入测试数据 → 再次 SD_ReadBlocks 读回比较 → SD_GetCardState 等待卡回到传输状态

1. 配置引脚与外设。 SD_PortInit 打开 SDIO 各引脚的 GPIO 时钟并把 CLK、CMD、D0~D3 配为复用推挽,SD_Init 再打开 SDIO 时钟、复位寄存器并按初始化分频写入外设参数。

src/sdcard.csrc/sdcard.c · SD_PortInit
    /* SDIO pin config */
    GPIO_InitPara.GPIO_Mode        = GPIO_MODE_AF_PP;
    GPIO_InitPara.GPIO_Slew_Rate   = GPIO_SLEW_RATE_FAST;
    GPIO_InitPara.GPIO_Pull        = GPIO_NO_PULL;
    GPIO_InitPara.GPIO_Current     = GPIO_DS_12mA;

    /* CLK */
    GPIO_InitPara.Pin              = SD_CLK_PIN;
    GPIO_InitPara.GPIO_Alternate   = SD_CLK_AF;
    GPIO_InitPeripheral(SD_CLK_PORT, &GPIO_InitPara);

    /* CMD */
    GPIO_InitPara.Pin              = SD_CMD_PIN;
    GPIO_InitPara.GPIO_Alternate   = SD_CMD_AF;
    GPIO_InitPeripheral(SD_CMD_PORT, &GPIO_InitPara);

    /* D0 */
    GPIO_InitPara.Pin              = SD_D0_PIN;
    GPIO_InitPara.GPIO_Alternate   = SD_D0_AF;
    GPIO_InitPeripheral(SD_D0_PORT, &GPIO_InitPara);

    /* D1 */
    GPIO_InitPara.Pin              = SD_D1_PIN;
    GPIO_InitPara.GPIO_Alternate   = SD_D1_AF;
    GPIO_InitPeripheral(SD_D1_PORT, &GPIO_InitPara);

    /* D2 */
    GPIO_InitPara.Pin              = SD_D2_PIN;
    GPIO_InitPara.GPIO_Alternate   = SD_D2_AF;
    GPIO_InitPeripheral(SD_D2_PORT, &GPIO_InitPara);

    /* D3 */
    GPIO_InitPara.Pin              = SD_D3_PIN;
    GPIO_InitPara.GPIO_Alternate   = SD_D3_AF;
    GPIO_InitPeripheral(SD_D3_PORT, &GPIO_InitPara);
src/sdcard.csrc/sdcard.c · SD_Init
    /* SDIOCLK = HCLK, SDIO_CLK = HCLK/(2 + ClkDiv) */
    /* SDIO_CLK for initialization should not exceed 400 KHz */
    SDIO_InitPara.ClkDiv            = SD_INIT_CLK_DIV;
    SDIO_InitPara.ClkEdge           = SDIO_CLK_EDGE_RISING;
    SDIO_InitPara.ClkBypass         = ClockBypass;
    SDIO_InitPara.ClkPwrSave        = SDIO_CLK_POWER_SAVE_DISABLE;
    SDIO_InitPara.BusWidth          = SDIO_BUS_WIDTH_1B;
    SDIO_InitPara.HardwareClkCtrl   = SDIO_HARDWARE_CLKCTRL_DISABLE;
    SDIO_Init(&SDIO_InitPara);

    /* Set Power State to ON */
    SDIO_SetPower(SDIO_POWER_CTRL_ON);

    /* Enable SDIO Clock */
    SDIO_EnableClock(ENABLE);

初始化阶段使用 1 位总线与不超过 400 kHz 的时钟,等卡识别完成后再切换到传输时钟与 4 位总线。

2. 上电与卡识别。 SD_PowerON 依次发送 CMD0、CMD8 与 CMD55/ACMD41(MMC 卡走 CMD1)完成上电和电压匹配,SD_InitCard 再用 CMD2、CMD3、CMD9、CMD10 取得卡地址与 CID、CSD 信息。

src/sdcard.csrc/sdcard.c · SD_PowerON
    /*Next, send a series of commands to start the card identification process*/
    /* CMD0: GO_IDLE_STATE. No CMDCTRL response required */
    error = SDIO_CmdGoIdleState();
    if (error != SDMMC_ERROR_NONE)
    {
        /* CMDCTRL Response TimeOut (wait for CMDSEND flag) */
        return (error);
    }

    /* Required power up waiting time before starting the SD initialization  sequence */
    Delay(SystemCoreClock/1000);    /* about 4ms */

    /* CMD8: SEND_IF_COND */
    /* Send CMD8 to verify SD card interface operating condition */
    /* Argument: - [31:12]: Reserved (shall be set to '0')
                 - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)
                 - [7:0]: Check Pattern (recommended 0xAA) */
    /* CMDCTRL Response: R7 */
    error = SDIO_CmdOperCond();
    if (error == SDMMC_ERROR_NONE) // If there is a response, card follows SD protocol version 2.0
    {
        SDCardInfo.CardVersion = CARD_V2_X;
    }
    else // No response, indicates 1.X or MMC card
    {
        SDCardInfo.CardVersion = CARD_V1_X;
    }
src/sdcard.csrc/sdcard.c · SD_PowerON
    /* Send cmd55 to detect SD card, MMC card, or unsupported card */
    /* If errorstatus is Command TimeOut, it is a MMC card */
    /* If errorstatus is SDMMC_ERROR_NONE it is a SD card: SD card 2.0 (voltage range mismatch)
       or SD card 1.x */
    error = SDIO_CmdAppCommand(0U);
    if (error == SDMMC_ERROR_NONE) // Responded to cmd55, SD card, may be 1.X, may be 2.0
    {
        /*Start to send the voltage range supported by SDIO circularly for a certain number of times*/
        /* Send ACMD41 SD_APP_OP_COND with Argument */
        while ((!validvoltage) && (count < SDMMC_MAX_VOLT_TRIAL))
        {
            /* Because acmd41 is ACMD command. So cmd55 must send to card first */
            /* SEND CMD55 APP_CMD with RCA as 0 */
            error = SDIO_CmdAppCommand(0U);
            if (error != SDMMC_ERROR_NONE)
            {
                return (error); // No response to cmd55, return
            }

            // acmd41,The command parameters consist of the supported voltage range and HCs bits. The HCS position is
            // used to distinguish whether the card is SDSC or SDHC
            error = SDIO_CmdAppOperCommand(SDMMC_VOLTAGE_WINDOW_SD | SDMMC_HIGH_CAPACITY);
            if (error != SDMMC_ERROR_NONE)
            {
                return (error); // Acmd41 not received correctly, error, return
            }

            /*If the card demand voltage is within the supply voltage range of SDIO, it will automatically power on and
             * mark PWR UP bit*/
            resp = SDIO_GetResp(SDIO_RESPONSE_1);
            validvoltage = (resp & SDMMC_CARD_POWER_UP); // Read the PWR up bit of the card's OCR register to see if it is working at normal voltage
            count++;       // Calculate number of cycles
        }
src/sdcard.csrc/sdcard.c · SD_InitCard
        /* CMD2 */
        error = SDIO_CmdAllSendCID();
        if (SDMMC_ERROR_NONE != error)
        {
            return (error);
        }

        CID_Tab[0] = SDIO_GetResp(SDIO_RESPONSE_1);
        CID_Tab[1] = SDIO_GetResp(SDIO_RESPONSE_2);
        CID_Tab[2] = SDIO_GetResp(SDIO_RESPONSE_3);
        CID_Tab[3] = SDIO_GetResp(SDIO_RESPONSE_4);

CMD8 用来确认卡是否支持 2.0 协议,SD 卡必须在 ACMD41 之前发送 CMD8。

3. 切换到传输时钟与 4 位总线。 SD_Init 在识别完成后用传输分频重新配置外设,SD_CofigBusWidth 通过 ACMD6 把卡与本机同时切到 4 位总线。

src/sdcard.csrc/sdcard.c · SD_Init
    error = SD_CofigBusWidth(BusWidth);
    if (error != SDMMC_ERROR_NONE)
    {
        /* CMDCTRL Response TimeOut (wait for CMDSEND flag) */
        return (error);
    }

    return (SDMMC_ERROR_NONE);
src/sdcard.csrc/sdcard.c · SD_CofigBusWidth
    else if(CARD_SDIO != SDCardInfo.CardType)
    {
        if (SDIO_BUS_WIDTH_8B == WideMode) // 2.0 SD does not support 8bits
        {
            return (SDMMC_ERROR_UNSUPPORTED_FEATURE);
        }
        else if (SDIO_BUS_WIDTH_4B == WideMode) // 4 data line mode
        {
            error = SD_EnableWideBus(ENABLE); // Use acmd6 to set the bus width and the transmission mode of the card
            if (SDMMC_ERROR_NONE != error)
            {
                return error;
            }

            SDIO_InitPara.BusWidth = SDIO_BUS_WIDTH_4B;
            SDIO_Init(&SDIO_InitPara);
        }
        else // Single data line mode
        {
            error = SD_EnableWideBus(DISABLE); // Use acmd6 to set the bus width and the transmission mode of the card
            if (SDMMC_ERROR_NONE != error)
            {
                return error;
            }

            SDIO_InitPara.BusWidth = SDIO_BUS_WIDTH_1B;
            SDIO_Init(&SDIO_InitPara);
        }
    }

总线宽度只能在卡被选中(CMD7)后的传输状态切换,本例把两端都切到 4 位。

4. 用 DMA 读写数据块。 SD_ReadBlocks 与 SD_WriteBlocks 先按块数配置数据通道、发送单块或多块命令,再启动 DMA 通道搬运数据,最后等待 DMA 完成标志与数据结束标志。

src/sdcard.csrc/sdcard.c · SD_ReadBlocks
    /* Config data register */
    InitData.DatTimeout        = SDMMC_DATATIMEOUT;
    InitData.DatLen            = NumberOfBlocks * SD_BLOCKSIZE;
    InitData.DatBlkSize        = SDIO_DATBLK_SIZE_512B;
    InitData.TransferDirection = SDIO_TRANSDIR_TOSDIO;
    InitData.TransferMode      = SDIO_TRANSMODE_BLOCK;
    InitData.DPSMConfig        = SDIO_DPSM_ENABLE;
    SDIO_ConfigData(&InitData);

    /* Send command for reading */
    if(NumberOfBlocks > 1U)
    {
        error = SDIO_CmdReadMultiBlock(ReadAddr);
    }
    else
    {
        error = SDIO_CmdReadSingleBlock(ReadAddr);
    }

    if(error != SDMMC_ERROR_NONE)
    {
        /* Clear all the static flags */
        SDIO_ClrFlag(SDIO_STATIC_FLAGS);
        return (error);
    }
src/sdcard.csrc/sdcard.c · SD_ReadBlocks
#if defined(SD_DMA_MODE)
    SD_DMA_RxConfig((uint32_t*)ReadBuf, ((NumberOfBlocks * SD_BLOCKSIZE)/4));
    SDIO_DMACmd(ENABLE);

    timeout = Timeout;
    while(1)
    {
        if( (DMA_GetFlagStatus(SDIO_DMA_ENDFLAG,SDIO_DMA) == SET)
           &&(SDIO_GetFlag(SDIO_FLAG_DATEND) == SET)    )
        {
            break;
        }

        if(0U == timeout )
        {
            break;
        }
        else
        {
            timeout--;
        }
    }

    SDIO_DMACmd(DISABLE);

    if(0U == timeout )
    {
        /* Clear all the static flags */
        SDIO_ClrFlag(SDIO_STATIC_FLAGS);
        return (SDMMC_ERROR_TIMEOUT);
    }
src/sdcard.csrc/sdcard.c · SD_WriteBlocks
#if defined(SD_DMA_MODE)

    SD_DMA_TxConfig((uint32_t*)SrcBuf, ((NumberOfBlocks * SD_BLOCKSIZE)/4));
    SDIO_DMACmd(ENABLE);

    timeout = Timeout;
    while(1)
    {
        if( (DMA_GetFlagStatus(SDIO_DMA_ENDFLAG,SDIO_DMA) == SET)
           &&(SDIO_GetFlag(SDIO_FLAG_DATEND) == SET)    )
        {
            break;
        }

        if(0U == timeout )
        {
            break;
        }
        else
        {
            timeout--;
        }
    }

    SDIO_DMACmd(DISABLE);

    if(0U == timeout )
    {
        /* Clear all the static flags */
        SDIO_ClrFlag(SDIO_STATIC_FLAGS);
        return (SDMMC_ERROR_TIMEOUT);
    }

数据长度按“块数 × 512 字节”写入数据控制寄存器,DMA 搬完由结束标志退出等待。

5. 擦除与主循环校验。 SD_Erase 先按卡类型换算地址并发送 CMD32、CMD33 与 CMD38,主循环在每一步之后查询卡状态,再读回写入的数据逐字节比较。

src/sdcard.csrc/sdcard.c · SD_Erase
    if(   (SDCardInfo.CardType == CARD_SDHC_SDXC)     \
        ||(SDCardInfo.CardType == CARD_MMC_HC)   ) // The address of the high capacity card is block(512bytes) number, not byte address
    {
        StrAddr /= 512;
        EndAddr /= 512;
    }

    if( (SDCardInfo.CardType == CARD_MMC_HC)    \
      ||(SDCardInfo.CardType == CARD_MMC_LC)    )
    {
        /* Send CMD35 MMC_ERASE_GRP_START with argument as addr  */
        error = SDIO_CmdEraseStartAdd(StrAddr);
    }
    else if(SDCardInfo.CardType != CARD_SDIO)
    {
         /* Send CMD32 SD_ERASE_GRP_START with argument as addr  */
        error = SDIO_CmdSDEraseStartAdd(StrAddr);
    }
    else
    {
        error = SDMMC_ERROR_NONE;
    }

    if(error != SDMMC_ERROR_NONE)
    {
        /* Clear all the static flags */
        SDIO_ClrFlag(SDIO_STATIC_FLAGS);
        return (error);
    }

    if( (SDCardInfo.CardType == CARD_MMC_HC)    \
      ||(SDCardInfo.CardType == CARD_MMC_LC)    )
    {
        /* Send CMD36 MMC_ERASE_GRP_END with argument as addr  */
        error = SDIO_CmdEraseEndAdd(EndAddr);
    }
    else if(SDCardInfo.CardType != CARD_SDIO)
    {
        /* Send CMD33 SD_ERASE_GRP_END with argument as addr  */
        error = SDIO_CmdSDEraseEndAdd(EndAddr);
    }
    else
    {
        error = SDMMC_ERROR_NONE;
    }

    if(error != SDMMC_ERROR_NONE)
    {
        /* Clear all the static flags */
        SDIO_ClrFlag(SDIO_STATIC_FLAGS);
        return (error);
    }

    /* Send CMD38 ERASE */
    error = SDIO_CmdErase();
    if(error != SDMMC_ERROR_NONE)
    {
        /* Clear all the static flags */
        SDIO_ClrFlag(SDIO_STATIC_FLAGS);
        return (error);
    }
src/main.csrc/main.c · main
        /* Initialize the SDIO interface and SD card */
        error = SD_Init(SDIO_CLK_BYPASS_DISABLE, SD_TRANSFER_CLK_DIV, SDIO_BUS_WIDTH_4B);
        if(error != SDMMC_ERROR_NONE)
        {
            log_debug("SD/MMC Card initialization failed,error=%d!\r\n",error);
            while(1);
        }
        else
        {
            log_debug("SD/MMC Card initialization success!\r\n");
        }
src/main.csrc/main.c · main
        /* Forth step: Check write result by read and compare */
        Memset(RxBuf,0x55U,TEST_BUF_LEN);
        error = SD_ReadBlocks(RxBuf,TEST_CARD_ADDR,TEST_BLOCK_NUM,SDMMC_DATATIMEOUT);
        if(error != SDMMC_ERROR_NONE)
        {
            log_debug("SD/MMC Card read after write failed,error=%d!\r\n",error);
            while(1);
        }

        /* Check card state */
        while(SD_GetCardState() != SDMMC_CARD_TRANSFER);

        /* Check write result */
        for(i=0;i<TEST_BUF_LEN;i++)
        {
            if(RxBuf[i] != TxBuf[i])
                break;
        }

        if(i<TEST_BUF_LEN)
        {
            log_debug("SD/MMC Card write check fail,i=%d,data=0x%02x!\r\n",i,RxBuf[i]);
            while(1);
        }
        else
        {
            log_debug("SD/MMC Card write success!\r\n");
        }

每一步都等待卡回到传输状态,只有读回数据与写入缓冲完全一致时才打印测试通过。

对应源码: src/main.c、src/sdcard.c

5.24.4 注意与排障

场景 检查与建议 来源
卡的数量 SDIO 同一时间仅支持一个 SD/SDIO/MMC 4.2 卡;
MMC 4.1 及更早版本可以挂接多个。
用户手册
数据总线宽度 上电或复位后默认只用 SDIO_DAT0 传数据;
MMC V3.31 及更早版本只支持 1 位数据线,4 位或 8 位总线须在主机初始化后自行配置。
用户手册
命令状态机空闲时序 命令状态机进出空闲状态时至少保持 8 个 SDIO_CLK 周期,以满足 NCC 与 NRC 时序限制。 用户手册
命令超时 命令超时时间固定为 64 个 SDIO_CLK 时钟周期,且不可配置。 用户手册
数据通道等待发送时序 数据通道在等待发送状态至少保持 2 个时钟周期,以满足 NWR 时序要求,即从收到卡响应到主机开始传输数据之间的间隔。 用户手册
SD 卡初始化顺序 初始化 SD 卡时必须在发送 ACMD41 之前先发送 CMD8;
卡识别过程中卡应工作在 FOD(400 kHz)时钟频率下。
用户手册
总线宽度切换时机 设置总线宽度的 ACMD6 命令仅在传输状态有效,即必须先用 CMD7 选择卡之后才能改变总线宽度。 用户手册
国民技术开发套件文档中心

按芯片系列在线查阅国民技术 MCU 开发套件的芯片资料、SDK、驱动 API 与 Demo 示例说明。

© 2026 国民技术股份有限公司 版权所有粤ICP备11069485号本站使用不含 Cookie 的匿名访问统计