STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo

这篇具有很好参考价值的文章主要介绍了STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


本节例程基于 野火电子的STM32F407的SD卡读写例程进行讲解。上一节中讲解了SD卡上电过程,这节将会讲解一下SD卡的初始化过程,包括 获取SD卡的CID、CSD和SD卡RCA地址

例程讲解-SD_InitializeCards & SD_GetCardInfo

CMD2:ALL_SEND_CID

CMD2的作用是通知所有卡通过CMD线返回CID值,CID值包括SD卡的识别号、制造商ID、OEMID、产品名称、版本号、序列号等信息,相当于是SD卡的身份证。
STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

命令发送程序

CMD2命令无需带参数,所以SDIO控制器可以直接发送CMD2命令

 SDIO_CmdInitStructure.SDIO_Argument = 0x0; // 不带参数
 SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ALL_SEND_CID; // 命令所以为CMD2
 SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long; // 长响应
 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; // 不等待
 SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; // 使能CPSM状态机
 SDIO_SendCommand(&SDIO_CmdInitStructure);

STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

命令响应程序

CMD2的响应是R2,其响应类型为长响应。其中bit[127:1]是其响应的数据。
STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

首先需要先判断SD卡的响应是否正常,如果响应正常,下一步就需要把128位的CID读出来。

static SD_Error CmdResp2Error(void)
{
  SD_Error errorstatus = SD_OK;
  uint32_t status;

  status = SDIO->STA;

  while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CTIMEOUT | SDIO_FLAG_CMDREND)))
  {
    status = SDIO->STA;
  }

  if (status & SDIO_FLAG_CTIMEOUT)
  {
    errorstatus = SD_CMD_RSP_TIMEOUT;
    SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT);
    return(errorstatus);
  }
  else if (status & SDIO_FLAG_CCRCFAIL)
  {
    errorstatus = SD_CMD_CRC_FAIL;
    SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);
    return(errorstatus);
  }

  /*!< Clear all the static flags */
  SDIO_ClearFlag(SDIO_STATIC_FLAGS);

  return(errorstatus);
}

// 读取128位CID
    CID_Tab[0] = SDIO_GetResponse(SDIO_RESP1);
    CID_Tab[1] = SDIO_GetResponse(SDIO_RESP2);
    CID_Tab[2] = SDIO_GetResponse(SDIO_RESP3);
    CID_Tab[3] = SDIO_GetResponse(SDIO_RESP4);

根据STM32F4X的数据手册可知,如果是长响应,高位的数据保存在SDIO_RESP1寄存器,低位保存在SDIO_RESP4寄存器
STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

CID数据解析

STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32
根据波形图可知SD卡的CID响应数据为0x9f54495344333247614af80704017158,CID的数据解析表如下

STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

下面就来对SD卡读取到CID数据进行解析

Name Field Width CID-slice Value
Manufacturer ID MID 8 [127:120] 0x9F
OEM/Application ID OID 16 [119:104] 0x5449
Product name PNM 40 [103:64] 0x5344333247
"SD32G"
Product revision PRV 8 [63:56] 0x61
Product serial number PSN 32 [55:24] 0x4af80704
reserved X 4 [23:20] 0
Manufacturing date MDT 12 [19:8] 0x171
CRC7 checksum CRC 7 [7:1] 0x2C
not used, always 1 x 1 [0:0] 0x1

CMD3:SEND_RELATIVE_ADDR

CMD3的作用是请求SD卡发布一个RCA,RCA的作用相当于是一个地址,这个RCA后续在读写SD卡中用于对SD卡进行寻址。

STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

命令发送程序

 SDIO_CmdInitStructure.SDIO_Argument = 0x00; // 不带参数
 SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_REL_ADDR; // 命令索引 CMD3
 SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; // 短响应
 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; // 不等待
 SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; // 使能 CPSM状态机
 SDIO_SendCommand(&SDIO_CmdInitStructure);

STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

命令响应程序

CMD3的响应是R6,其中SD卡的RCA在响应数据的bit[31:16]
STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32
在程序中会先判断SD卡的响应是否正常,如果响应正常就通过SDIO_RESP1寄存器读取R6响应的数据,然后保存高16位的RCA地址。

static SD_Error CmdResp6Error(uint8_t cmd, uint16_t *prca)
{
  SD_Error errorstatus = SD_OK;
  uint32_t status;
  uint32_t response_r1;

  status = SDIO->STA;

  while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CTIMEOUT | SDIO_FLAG_CMDREND)))
  {
    status = SDIO->STA;
  }

  if (status & SDIO_FLAG_CTIMEOUT)
  {
    errorstatus = SD_CMD_RSP_TIMEOUT;
    SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT);
    return(errorstatus);
  }
  else if (status & SDIO_FLAG_CCRCFAIL)
  {
    errorstatus = SD_CMD_CRC_FAIL;
    SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);
    return(errorstatus);
  }

  /*!< Check response received is of desired command */
  if (SDIO_GetCommandResponse() != cmd)
  {
    errorstatus = SD_ILLEGAL_CMD;
    return(errorstatus);
  }

  /*!< Clear all the static flags */
  SDIO_ClearFlag(SDIO_STATIC_FLAGS);

  /*!< We have received response, retrieve it.  */
  response_r1 = SDIO_GetResponse(SDIO_RESP1);

  if (SD_ALLZERO == (response_r1 & (SD_R6_GENERAL_UNKNOWN_ERROR | SD_R6_ILLEGAL_CMD | SD_R6_COM_CRC_FAILED)))
  {
    *prca = (uint16_t) (response_r1 >> 16);
    return(errorstatus);
  }

  if (response_r1 & SD_R6_GENERAL_UNKNOWN_ERROR)
  {
    return(SD_GENERAL_UNKNOWN_ERROR);
  }

  if (response_r1 & SD_R6_ILLEGAL_CMD)
  {
    return(SD_ILLEGAL_CMD);
  }

  if (response_r1 & SD_R6_COM_CRC_FAILED)
  {
    return(SD_COM_CRC_FAILED);
  }

  return(errorstatus);
}

STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

CMD9:SEND_CSD

CMD9的作用是获取SD卡的CSD数据,CSD数据主要包含SD卡一些基本状态信息,包括SD的块大小、SD卡传输速率、SD卡的擦除扇区大小等信息。CMD9命令需要带参数,其参数是SD卡的RCA地址
STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

命令发送程序

 SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)(rca << 16); // 参数RCA地址
 SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_CSD; // 命令索引 CMD9
 SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long; // 长响应
 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; // 不等待
 SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; // 使能CPSM状态机
 SDIO_SendCommand(&SDIO_CmdInitStructure);

STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

命令响应程序

CMD9的响应是R2,长响应,CSD的返回数据是128位。
STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

static SD_Error CmdResp2Error(void)
{
  SD_Error errorstatus = SD_OK;
  uint32_t status;

  status = SDIO->STA;

  while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CTIMEOUT | SDIO_FLAG_CMDREND)))
  {
    status = SDIO->STA;
  }

  if (status & SDIO_FLAG_CTIMEOUT)
  {
    errorstatus = SD_CMD_RSP_TIMEOUT;
    SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT);
    return(errorstatus);
  }
  else if (status & SDIO_FLAG_CCRCFAIL)
  {
    errorstatus = SD_CMD_CRC_FAIL;
    SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL);
    return(errorstatus);
  }

  /*!< Clear all the static flags */
  SDIO_ClearFlag(SDIO_STATIC_FLAGS);

  return(errorstatus);
}
CSD_Tab[0] = SDIO_GetResponse(SDIO_RESP1);
CSD_Tab[1] = SDIO_GetResponse(SDIO_RESP2);
CSD_Tab[2] = SDIO_GetResponse(SDIO_RESP3);
CSD_Tab[3] = SDIO_GetResponse(SDIO_RESP4);

CSD的数据读取跟CID的数据读取是一样,不同的是两个数据的解析方法不一样

CSD数据解析

STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

从波形图可知CSD的数据为0x400e00325b590000e68f7f800a400018,下面就对读取到的CSD数据进行解析。
STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

Name Field Width CID-slice Value
CSD structure CSD_STRUCTURE 2 [127:126] 0x1
reserved X 6 [125:120] 0
data read access-time-1 TAAC 8 [119:112] 0xE
"SD32G"
data read access-time-2 in CLK cycles (NSAC*100) NSAC 8 [111:104] 0x0
max. data transfer rate TRAN_SPEED 8 [103:96] 0x32
card command classes CCC 12 [95:84] 0x5b5
max. read data block length READ_BL_LEN 4 [83:80] 0x9
partial blocks for read allowed READ_BL_PARTIAL 1 [79:79] 0x0
write block misalignment WRITE_BLK_MISALIGN 1 [78:78] 0x0
read block misalignment READ_BLK_MISALIGN 1 [77:77] 0x0
DSR implemented DSR_IMP 1 [76:76] 0x0
reserved X 6 [75:70] 0x0
device size C_SIZE 22 [69:48] 0xE68F
reserved X 1 [47:47] 0x0
erase single block enable ERASE_BLK_EN 1 [46:46] 0x1
erase sector size SECTOR_SIZE 7 [45:39] 0x7F
write protect group size WP_GRP_SIZE 7 [39:32] 0x0
write protect group enable WP_GRP_ENABLE 1 [31:31] 0x0
reserved X 2 [30:29] 0x0
write speed factor R2W_FACTOR 2 [28:26] 0x2
max. write data block length WRITE_BL_LEN 4 [25:22] 0x9
partial blocks for write allowed WRITE_BL_PARTIAL 1 [21:21] 0x0
reserved X 5 [20:16] 0x0
File format group FILE_FORMAT_GRP 1 [15:15] 0x0
copy flag COPY 1 [14:14] 0x0
permanent write protection PERM_WRITE_PROTECT 1 [13:13] 0x0
temporary write protection TMP_WRITE_PROTECT 1 [12:12] 0x0
File format FILE_FORMAT 2 [11:10] 0x0
reserved X 2 [9:8] 0x0
CRC CRC 7 [7:1] 0xC
not used, always'1' X 1 [0:0] 0x1
CSD结构版本

CSD_STRUCTURE区域代表的是CSD寄存器结构使用的解析版本号,在SD卡的发展中使用了不同的CSD版本,在上面的例程中CSD_STRUCTURE的值是0x01,则代表使用的CSD V2.0的版本
STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

READ_BL_LEN

最大的数据块读取长度,数值为9则代表是512字节
STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo,STM32学习,stm32

SD卡容量

根据上面的CSD数据我们可以计算出SD卡的容量大小,其计算公式如下memory capacity = (C_SIZE+1) * 512KByte
memory capacity = (0xE68F + 1) * 512 = 30,220,288(Byte) = 29512(M) = 28G

获取SD卡信息

MCU读取到SD卡的CSD和CID数据后,就可以根据上面的表格进行数据的解析文章来源地址https://www.toymoban.com/news/detail-745692.html

SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo)
{
  SD_Error errorstatus = SD_OK;
  uint8_t tmp = 0;

  cardinfo->CardType = (uint8_t)CardType;
  cardinfo->RCA = (uint16_t)RCA;

  /*!< Byte 0 */
  tmp = (uint8_t)((CSD_Tab[0] & 0xFF000000) >> 24);
  cardinfo->SD_csd.CSDStruct = (tmp & 0xC0) >> 6;
  cardinfo->SD_csd.SysSpecVersion = (tmp & 0x3C) >> 2;
  cardinfo->SD_csd.Reserved1 = tmp & 0x03;

  /*!< Byte 1 */
  tmp = (uint8_t)((CSD_Tab[0] & 0x00FF0000) >> 16);
  cardinfo->SD_csd.TAAC = tmp;

  /*!< Byte 2 */
  tmp = (uint8_t)((CSD_Tab[0] & 0x0000FF00) >> 8);
  cardinfo->SD_csd.NSAC = tmp;

  /*!< Byte 3 */
  tmp = (uint8_t)(CSD_Tab[0] & 0x000000FF);
  cardinfo->SD_csd.MaxBusClkFrec = tmp;

  /*!< Byte 4 */
  tmp = (uint8_t)((CSD_Tab[1] & 0xFF000000) >> 24);
  cardinfo->SD_csd.CardComdClasses = tmp << 4;

  /*!< Byte 5 */
  tmp = (uint8_t)((CSD_Tab[1] & 0x00FF0000) >> 16);
  cardinfo->SD_csd.CardComdClasses |= (tmp & 0xF0) >> 4;
  cardinfo->SD_csd.RdBlockLen = tmp & 0x0F;

  /*!< Byte 6 */
  tmp = (uint8_t)((CSD_Tab[1] & 0x0000FF00) >> 8);
  cardinfo->SD_csd.PartBlockRead = (tmp & 0x80) >> 7;
  cardinfo->SD_csd.WrBlockMisalign = (tmp & 0x40) >> 6;
  cardinfo->SD_csd.RdBlockMisalign = (tmp & 0x20) >> 5;
  cardinfo->SD_csd.DSRImpl = (tmp & 0x10) >> 4;
  cardinfo->SD_csd.Reserved2 = 0; /*!< Reserved */

  if ((CardType == SDIO_STD_CAPACITY_SD_CARD_V1_1) || (CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0))
  {
    cardinfo->SD_csd.DeviceSize = (tmp & 0x03) << 10;

    /*!< Byte 7 */
    tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF);
    cardinfo->SD_csd.DeviceSize |= (tmp) << 2;

    /*!< Byte 8 */
    tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24);
    cardinfo->SD_csd.DeviceSize |= (tmp & 0xC0) >> 6;

    cardinfo->SD_csd.MaxRdCurrentVDDMin = (tmp & 0x38) >> 3;
    cardinfo->SD_csd.MaxRdCurrentVDDMax = (tmp & 0x07);

    /*!< Byte 9 */
    tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16);
    cardinfo->SD_csd.MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5;
    cardinfo->SD_csd.MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2;
    cardinfo->SD_csd.DeviceSizeMul = (tmp & 0x03) << 1;
    /*!< Byte 10 */
    tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8);
    cardinfo->SD_csd.DeviceSizeMul |= (tmp & 0x80) >> 7;
    
    cardinfo->CardCapacity = (cardinfo->SD_csd.DeviceSize + 1) ;
    cardinfo->CardCapacity *= (1 << (cardinfo->SD_csd.DeviceSizeMul + 2));
    cardinfo->CardBlockSize = 1 << (cardinfo->SD_csd.RdBlockLen);
    cardinfo->CardCapacity *= cardinfo->CardBlockSize;
  }
  else if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  {
    /*!< Byte 7 */
    tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF);
    cardinfo->SD_csd.DeviceSize = (tmp & 0x3F) << 16;

    /*!< Byte 8 */
    tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24);

    cardinfo->SD_csd.DeviceSize |= (tmp << 8);

    /*!< Byte 9 */
    tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16);

    cardinfo->SD_csd.DeviceSize |= (tmp);

    /*!< Byte 10 */
    tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8);
    
    cardinfo->CardCapacity = ((uint64_t)cardinfo->SD_csd.DeviceSize + 1) * 512 * 1024;
    cardinfo->CardBlockSize = 512;    
  }


  cardinfo->SD_csd.EraseGrSize = (tmp & 0x40) >> 6;
  cardinfo->SD_csd.EraseGrMul = (tmp & 0x3F) << 1;

  /*!< Byte 11 */
  tmp = (uint8_t)(CSD_Tab[2] & 0x000000FF);
  cardinfo->SD_csd.EraseGrMul |= (tmp & 0x80) >> 7;
  cardinfo->SD_csd.WrProtectGrSize = (tmp & 0x7F);

  /*!< Byte 12 */
  tmp = (uint8_t)((CSD_Tab[3] & 0xFF000000) >> 24);
  cardinfo->SD_csd.WrProtectGrEnable = (tmp & 0x80) >> 7;
  cardinfo->SD_csd.ManDeflECC = (tmp & 0x60) >> 5;
  cardinfo->SD_csd.WrSpeedFact = (tmp & 0x1C) >> 2;
  cardinfo->SD_csd.MaxWrBlockLen = (tmp & 0x03) << 2;

  /*!< Byte 13 */
  tmp = (uint8_t)((CSD_Tab[3] & 0x00FF0000) >> 16);
  cardinfo->SD_csd.MaxWrBlockLen |= (tmp & 0xC0) >> 6;
  cardinfo->SD_csd.WriteBlockPaPartial = (tmp & 0x20) >> 5;
  cardinfo->SD_csd.Reserved3 = 0;
  cardinfo->SD_csd.ContentProtectAppli = (tmp & 0x01);

  /*!< Byte 14 */
  tmp = (uint8_t)((CSD_Tab[3] & 0x0000FF00) >> 8);
  cardinfo->SD_csd.FileFormatGrouop = (tmp & 0x80) >> 7;
  cardinfo->SD_csd.CopyFlag = (tmp & 0x40) >> 6;
  cardinfo->SD_csd.PermWrProtect = (tmp & 0x20) >> 5;
  cardinfo->SD_csd.TempWrProtect = (tmp & 0x10) >> 4;
  cardinfo->SD_csd.FileFormat = (tmp & 0x0C) >> 2;
  cardinfo->SD_csd.ECC = (tmp & 0x03);

  /*!< Byte 15 */
  tmp = (uint8_t)(CSD_Tab[3] & 0x000000FF);
  cardinfo->SD_csd.CSD_CRC = (tmp & 0xFE) >> 1;
  cardinfo->SD_csd.Reserved4 = 1;


  /*!< Byte 0 */
  tmp = (uint8_t)((CID_Tab[0] & 0xFF000000) >> 24);
  cardinfo->SD_cid.ManufacturerID = tmp;

  /*!< Byte 1 */
  tmp = (uint8_t)((CID_Tab[0] & 0x00FF0000) >> 16);
  cardinfo->SD_cid.OEM_AppliID = tmp << 8;

  /*!< Byte 2 */
  tmp = (uint8_t)((CID_Tab[0] & 0x000000FF00) >> 8);
  cardinfo->SD_cid.OEM_AppliID |= tmp;

  /*!< Byte 3 */
  tmp = (uint8_t)(CID_Tab[0] & 0x000000FF);
  cardinfo->SD_cid.ProdName1 = tmp << 24;

  /*!< Byte 4 */
  tmp = (uint8_t)((CID_Tab[1] & 0xFF000000) >> 24);
  cardinfo->SD_cid.ProdName1 |= tmp << 16;

  /*!< Byte 5 */
  tmp = (uint8_t)((CID_Tab[1] & 0x00FF0000) >> 16);
  cardinfo->SD_cid.ProdName1 |= tmp << 8;

  /*!< Byte 6 */
  tmp = (uint8_t)((CID_Tab[1] & 0x0000FF00) >> 8);
  cardinfo->SD_cid.ProdName1 |= tmp;

  /*!< Byte 7 */
  tmp = (uint8_t)(CID_Tab[1] & 0x000000FF);
  cardinfo->SD_cid.ProdName2 = tmp;

  /*!< Byte 8 */
  tmp = (uint8_t)((CID_Tab[2] & 0xFF000000) >> 24);
  cardinfo->SD_cid.ProdRev = tmp;

  /*!< Byte 9 */
  tmp = (uint8_t)((CID_Tab[2] & 0x00FF0000) >> 16);
  cardinfo->SD_cid.ProdSN = tmp << 24;

  /*!< Byte 10 */
  tmp = (uint8_t)((CID_Tab[2] & 0x0000FF00) >> 8);
  cardinfo->SD_cid.ProdSN |= tmp << 16;

  /*!< Byte 11 */
  tmp = (uint8_t)(CID_Tab[2] & 0x000000FF);
  cardinfo->SD_cid.ProdSN |= tmp << 8;

  /*!< Byte 12 */
  tmp = (uint8_t)((CID_Tab[3] & 0xFF000000) >> 24);
  cardinfo->SD_cid.ProdSN |= tmp;

  /*!< Byte 13 */
  tmp = (uint8_t)((CID_Tab[3] & 0x00FF0000) >> 16);
  cardinfo->SD_cid.Reserved1 |= (tmp & 0xF0) >> 4;
  cardinfo->SD_cid.ManufactDate = (tmp & 0x0F) << 8;

  /*!< Byte 14 */
  tmp = (uint8_t)((CID_Tab[3] & 0x0000FF00) >> 8);
  cardinfo->SD_cid.ManufactDate |= tmp;

  /*!< Byte 15 */
  tmp = (uint8_t)(CID_Tab[3] & 0x000000FF);
  cardinfo->SD_cid.CID_CRC = (tmp & 0xFE) >> 1;
  cardinfo->SD_cid.Reserved2 = 1;
  
  return(errorstatus);
}

SD卡初始化流程

  1. 发送CMD2获取CID数据
  2. 发送CMD3获取SD卡的RCA地址
  3. 发送CMD9获取SD卡的CSD数据
  4. 根据CID和CSD表格解析数据

到了这里,关于STM32F4X SDIO(七) 例程讲解-SD_InitializeCards & SD_GetCardInfo的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32F4X RNG随机数发生器

    随机数顾名思义就是随机产生的数字,这种数字最大的特点就是其不确定性,你不知道它下一次产生的数字是什么。随机数被广泛应用于密码学、模拟实验、游戏开发领域等。 RNG的控制寄存器的bit0使能随机数发生器是否工作,bit1则使能是否使用中断 状态寄存器是判断随机数

    2024年02月10日
    浏览(48)
  • 单片机:STM32F4x HAL库软硬SPI驱动ST7735s 1.8寸LCD屏幕

    说明:此篇为学习记录。可能存在错误或者不足。如有问题请指出。 主控芯片:STM32F411CEU6 主控开发板:WeAct STM32F411CEU6最小系统板 TFT-LCD屏幕:合宙1.8寸TFT-LCD,驱动为ST7735s MDK版本:5,32 HAL库版本:1.27.1 STM32CubeMX版本:6.7.0 ST7735s支持8080并口,3线和4线串行接口,模块的驱动方

    2024年02月03日
    浏览(59)
  • STM32F407ZGT6正点原子F4探索者开发板 -- 跑马灯例程

    LED0 - PF9 LED1 - PF10 PF9 = 0, LED0 亮,PF9 = 1,LED0 灭 PF10 = 0, LED1 亮,PF10 = 1,LED1 灭

    2024年02月15日
    浏览(56)
  • stm32读写SD卡(SDIO模式)

    目录 一、SD卡简介 二、源码下载 三、移植条件 1、芯片参数 2、硬件连接 四、驱动代码 1、依赖宏如下 2、驱动代码实现 3、测试代码 4、运行截图 五、总结 SD卡有SDIO驱动模式和SPI驱动模式,本例中使用SDIO模式驱动SD卡。 https://download.csdn.net/download/qq_30095023/88702705 https://downl

    2024年01月24日
    浏览(49)
  • (第48-59讲)STM32F4单片机,FreeRTOS【事件标志、任务通知、软件定时器、Tickless低功耗】【纯文字讲解】【】

    【吐血总结】FreeRTOS难点、Systick中断-滴答定时器、PendSV中断-任务切换、SVC中断-系统底层、时间片调度-时钟节拍【已完结】 (第1-8讲)STM32F4单片机,FreeRTOS基础知识总结【视频笔记、代码讲解】【正点原子】【原创】 (第9-10讲)STM32F4单片机,FreeRTOS任务创建和删除(动态方

    2024年02月01日
    浏览(65)
  • STM32——SDIO的学习(驱动SD卡)(理论篇)

    目录 一、SD卡简介 1.1历史 1.2 tf卡和SD卡的区别 1.3 mmc,emmc,nand,flash的关系 1.4 SD卡的规格等级 1.4.1按容量分 1.4.2 class等级 1.4.3 UHS总线模式 1.4.4 UHS速度等级 1.4.5 VSC视频速度等级 二、SD卡的内部结构 三、SDIO的学习 3.1 SDIO的主要功能 3.2 SDIO总线拓扑 ​3.3 SDIO功能描述  3.3.1 SD

    2024年02月16日
    浏览(49)
  • STM32——SDIO的学习(驱动SD卡)(实战篇)

    目录 一、SDIO寄存器 1.1 SDIO电源控制寄存器(SDIO_POWER) 1.2 SDIO时钟控制寄存器(SDIO_CLKCR) 1.3 SDIO参数寄存器(SDIO_ARG) 1.4 SDIO命令寄存器(SDIO_CMD) 1.5 SDIO命令响应寄存器(SDIO_RESPCMD) 1.6 SDIO响应 1..4 寄存器(SDIO_RESPx) 1.7 SDIO数据定时器寄存器(SDIO_DTIMER) 1.8 SDIO数据长度寄存器(SDIO_DLEN) 1.9 SDI

    2024年02月16日
    浏览(66)
  • STM32CubeMX教程27 SDIO - 读写SD卡

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 逻辑分析仪nanoDLA 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX软件配置STM32F407开发板 SDIO读写4线SD卡,实现轮询方式读写SD卡、以中断方式读取SD卡和以DMA方式读取SD卡 安全数码

    2024年02月19日
    浏览(67)
  • stm32在SDIO模式下SD写入错误的问题

    1、问题描述 使用FAT32 f_write 多次执行写操作时,会报FR_DISK_ERR错误,而且是刚开始写不报错,写几次后会一直报错。 设断点跟踪到HAL_SD_WriteBlocks中,在调用SDMMC_CmdWriteMultiBlock时,会报SDMMC_ERROR_TX_UNDERRUN,意思 是Transmit FIFO underrun 2、原因分析 如下图所示,SDMMC开始写操作时,首

    2023年04月24日
    浏览(47)
  • STM32CubeMX系列09——SDIO(SD卡读写、SD卡移植FATFS文件系统)

    ==== 文章汇总(有代码汇总) ==== 准备看看这方面的知识,一时间还没不清有什么区别,先补补课,不需要的跳过。 参考文章(内容来源):http://www.360doc.com/content/21/1125/22/59057945_1005908465.shtml 主要写这两个:SD卡、TF卡 共同点:SD、TF、MMC都是在MMC基础上演化发展不同的规范,

    2024年02月09日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包