主頁 >  其他 > 【STM32】STM32 SDIO SD卡讀寫測驗(三)-- SD_Init之Init Card階段

【STM32】STM32 SDIO SD卡讀寫測驗(三)-- SD_Init之Init Card階段

2021-02-28 11:45:04 其他

相關文章

《【SDIO】SDIO、SD卡、FatFs檔案系統相關文章索引》

1. 前言

本篇文章主要是介紹stm324x9i_eval_sdio_sd.c里面SD_Init()函式完整的程序,它主要是實作了SDIO的初始化SD卡的Power UPSD卡的初始化獲取SD卡的相關資訊等,下面會詳細介紹SD卡的初始化獲取SD卡的相關資訊的分析,

2. SD_InitializeCards()

SD_InitializeCards()主要的功能是初始化SD卡獲取CID和RCA的資訊,并進入Standby狀態,主要涉及到的函式如下:

  • CMD2: SD_CMD_ALL_SEND_CID
  • CMD3: SD_CMD_SET_REL_ADDR
  • CMD9: SD_CMD_SEND_CSD

2.1 CMD2: SD_CMD_ALL_SEND_CID

CMD2: SD_CMD_ALL_SEND_CID是通知所有卡通過 CMD 線回傳 CID值,CID值是卡的唯一標識,在卡發送CID后,它進入識別狀態,

#define SD_CMD_ALL_SEND_CID                        ((uint8_t)2)

/*!< Send CMD2 ALL_SEND_CID */
SDIO_CmdInitStructure.SDIO_Argument = 0x0;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ALL_SEND_CID;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

發送出去的波形如下:

發送CMD2命令后,呼叫CmdResp2Error()獲取SDIO 狀態暫存器 (SDIO_STA) Value,通過回傳的狀態Value來判斷命令回應是否已經正確被接收,如果回應被正確被接受,通過訪問SDIO 回應 1…4 暫存器 (SDIO_RESPx)來獲取CID的值,

errorstatus = CmdResp2Error();

if (SD_OK != errorstatus)
{
  return(errorstatus);
}

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);

從SD2.0協議里面可以了解到CMD2的response格式是R2,R2主要獲取CID或者CSD值,


為什么獲取CID值需要讀取SDIO Response 1…4暫存器?
因為在STM32的SDIO相關暫存器可以了解到關于127 Bit 長回應會用到SDIO_RESP1..4這4個暫存器拼接成的(如下圖STM32 SDIO Datasheet所示),所以這里需要訪問這4個暫存器,如果命令回應的引數的長度是32 Bit 短回應,那么就只需要讀取SDIO_RESP1暫存器的Value,

R1、R2、R3、R6、R7SDIO_RESP1…4 這2個概率容易弄混:

  • R1、R2、R3、R6、R7:這個是SD2.0《Physical Specification Version 2.00》 協議規定CMD回應命令格式,
  • SDIO_RESP1..4:這個是STM32暫存器存放命令回應引數的值,


邏輯分析儀抓取波形如下:

從上面的波形可以獲取到CID值為:0x03534453433332478049D204AD012ADF,關于CID的表格如下:

NameFieldWidthCID-sliceValue
Manufacturer IDMID8[127:120]0x03
OEM/Application IDOID16[119:104]0x5344
Product namePNM40[103:64]"S C 3 2 G"
(0x5343333247)
Product revisionPRV8[63:56]0x80
Product serial numberPSN32[55:24]0x49D204AD
reserved--4[23:20]0
Manufacturing dateMDT12[19:8]0x12A
(October 2018)
CRC7 checksumCRC7[7:1]0x6F
not used, always 1-1[0:0]1

PNM:
The product name is a string, 5-character ASCII string.
MDT:
The “m” field [11:8] is the month code. 1 = January.
The “y” field [19:12] is the year code. 0 = 2000.

2.2 CMD3: SD_CMD_SET_REL_ADDR

CMD3: SD_CMD_SET_REL_ADDR 主機發出CMD3 (SEND_RELATIVE_ADDR)請求SD卡發布一個新的相對卡地址(RCA),它比CID短,在未來的資料傳輸模式中用于給SD卡尋址,一旦接收到RCA,SD卡狀態就會變為待機狀態,此時,如果主機希望分配另一個RCA號碼,它可以通過向卡發送另一個CMD3命令來要求卡發布一個新號碼,最后發布的RCA是SD卡的實際RCA號,

#define SD_CMD_SET_REL_ADDR                        ((uint8_t)3) /*!< SDIO_SEND_REL_ADDR for SD Card */

/*!< Send CMD3 SET_REL_ADDR with argument 0 */
/*!< SD Card publishes its RCA. */
SDIO_CmdInitStructure.SDIO_Argument = 0x00;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_REL_ADDR;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

因為發送命令CMD3的Argument是stuff bits,所以這里需要填寫0x00,實際發送出去的波形如下:

發送CMD3命令后,呼叫CmdResp6Error()獲取SDIO 狀態暫存器 (SDIO_STA) Value,通過回傳的狀態Value來判斷命令回應是否已經正確被接收,如果回應被正確被接受,通過訪問SDIO 命令回應暫存器 (SDIO_RESPCMD)來獲取Response Command Index,判斷Response Command Index是否等于CMD3,然后訪問SDIO 回應 1 暫存器 (SDIO_RESP1)來獲取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;
  }

  ...

  /*!< 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);
  }

  ...

  return(errorstatus);
}

從SD2.0協議里面可以了解到CMD3的response格式是R6,R6主要獲取RCA和Card Status Bits的值,


邏輯分析儀抓取波形可以了解到 RCA = 0xAAAA,波形如下:

2.3 CMD9: SD_CMD_SEND_CSD

CMD9: SD_CMD_SEND_CSD主機發出SEND_CSD(CMD9)以獲取與SD卡有關的資料(CSD暫存器),例如塊長度、卡的儲存容量等,

#define SD_CMD_SEND_CSD                            ((uint8_t)9)

/*!< Send CMD9 SEND_CSD with argument as card's RCA */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)(rca << 16); // RCA = 0xAAAA
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_CSD;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

發送CMD9命令時,Argument需要填寫RCA,前面已經獲取到 RCA = 0xAAAA,所以實際發送的命令波形如下:

發送CMD9命令后,呼叫CmdResp2Error()獲取SDIO 狀態暫存器 (SDIO_STA) Value,通過回傳的狀態Value來判斷命令回應是否已經正確被接收,如果回應被正確被接受,通過訪問SDIO 回應 1…4 暫存器 (SDIO_RESPx)來獲取CSD的值,

errorstatus = CmdResp2Error();

if (SD_OK != errorstatus)
{
  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);

從SD2.0協議里面可以了解到CMD2的response格式是R2,R2主要獲取CID或者CSD值,


邏輯分析儀抓取波形如下:

從上面的波形可以獲取到CSD值為:0x400E00325B590000EDC87F800A4040C3,關于CSD的表格如下:

NameFieldWidthValueCell TypeCID-slice
CSD structureCSD_STRUCTURE201bR[127:126]
reserved-600 0000bR[125:120]
data read access-time(TAAC)80EhR[119:112]
data read access-time
in CLK cycles (NSAC*100)
(NSAC)800hR[111:104]
max. data transfer rate(TRAN_SPEED)832h or 5AhR[103:96]
card command classesCCC12010110110101bR[95:84]
max. read data block length(READ_BL_LEN)49R[83:80]
partial blocks for read allowed(READ_BL_PARTIAL)10R[79:79]
write block misalignment(WRITE_BLK_MISALIGN)10R[78:78]
read block misalignment(READ_BLK_MISALIGN)10R[77:77]
DSR implementedDSR_IMP10R[76:76]
reserved -600 0000bR[75:70]
device sizeC_SIZE2200 EDC8hR[69:48]
reserved -10R[47:47]
erase single block enable(ERASE_BLK_EN) 11R[46:46]
erase sector size(SECTOR_SIZE)77FhR[45:39]
write protect group size (WP_GRP_SIZE) 70000000bR[38:32]
write protect group enable(WP_GRP_ENABLE) 10R[31:31]
reserved-200bR[30:29]
write speed factor (R2W_FACTOR)3010bR[28:26]
max. write data block length(WRITE_BL_LEN) 49R[25:22]
partial blocks for write allowed(WRITE_BL_PARTIAL) 10R[21:21]
reserved -500000bR[20:16]
File format group(FILE_FORMAT_GRP)10R[15:15]
copy flag (OTP)COPY11R/W(1)[14:14]
permanent write protectionPERM_WRITE_PROTECT10R/W(1)[13:13]
temporary write protectionTMP_WRITE_PROTECT10R/W[12:12]
File format(FILE_FORMAT) 200bR[11:10]
reserved-200bR[9:8]
CRCCRC7110 0001bR/W[7:1]
not used, always’1’ -11-[0:0]
  • CSD_STRUCTURE
    CSD_STRUCTURE指示了CSD structure version,根據上面決議的資料,所以選擇的是CSD Version 2.0,

  • TRAN_SPEED
    下表定義了每條資料線的最大資料傳輸速率- TRAN_SPEED:

    當時鐘等于25MHz時,這個域總是0_0110_010b (032h),如果時鐘等于50MHz時,這個域總是0_1011_010b (05Ah)

  • READ_BL_LEN
    READ_BL_LEN最大讀資料塊長度計算公式為2READ_BL_LEN,最大塊長度應該在512…2048個位元組,注意,在SD存盤卡的WRITE_BL_LEN總是等于READ_BL_LEN,根據上面資料的決議,所以Block Length的值為 29 = 512 Bytes

3.SDIO_Init()

SDIO_Init()主要是配置SDIO時鐘控制暫存器(SDIO_CLKCR),因為接下來SD卡會進入傳輸模式,所以這里需要提高SDIO Clock,這里將SDIO_CK 頻率設定為25MHz,

/** 
  * @brief  SDIO Data Transfer Frequency (25MHz max) 
  */
#define SDIO_TRANSFER_CLK_DIV            ((uint8_t)0x0)

/*!< Configure the SDIO peripheral */
/*!< SDIO_CK = SDIOCLK / (SDIO_TRANSFER_CLK_DIV + 2) */
/*!< on STM32F4xx devices, SDIOCLK is fixed to 48MHz */
SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV;
SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;
SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;
SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;
SDIO_Init(&SDIO_InitStructure);

名稱描述Value備注
CLKDIV時鐘分頻系數 (Clock divide factor)
該欄位定義輸入時鐘 (SDIOCLK) 與輸出時鐘 (SDIO_CK) 之間的分頻系數:
SDIO_CK 頻率 = SDIOCLK / [CLKDIV + 2]
0x00SDIO_CK 頻率 = SDIOCLK / [CLKDIV + 2]
24M = 48M / [0x00 + 2]

設定SDIO_CK之前,頻率為400KHz左右,如下:

設定SDIO_CK之后,頻率為25MHz左右,如下:

4.SD_GetCardInfo()

SD_GetCardInfo()主要作用是決議前面獲取到CSD的值,具體可以參考上面的表格,這里不重復介紹了,

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 */
 
  ...

}

5.SD_SelectDeselect()

SD_SelectDeselect()主要作用是通過CMD7選擇對應的RCA地址的SD卡進入傳輸模式,前面已經獲取到RCA地址為 RCA = 0xAAAACMD7用于選擇一張SD卡并將其置于傳輸狀態,在同一時刻只能有一張卡處于傳輸狀態,如果先前選擇的卡處于傳輸狀態,它與主機的連接將被釋放,它將回傳到 Stand-by 狀態,

errorstatus = SD_SelectDeselect((uint32_t) (SDCardInfo.RCA << 16));  // RCA = 0xAAAA

-------------------------------------------------->

SD_Error SD_SelectDeselect(uint64_t addr)
{
  SD_Error errorstatus = SD_OK;

  /*!< Send CMD7 SDIO_SEL_DESEL_CARD */
  SDIO_CmdInitStructure.SDIO_Argument =  (uint32_t)addr;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEL_DESEL_CARD;
  SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
  SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
  SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
  SDIO_SendCommand(&SDIO_CmdInitStructure);

  errorstatus = CmdResp1Error(SD_CMD_SEL_DESEL_CARD);

  return(errorstatus);
}

實際發送出去的波形如下:

發送CMD7命令后,呼叫CmdResp1Error獲取SDIO 狀態暫存器 (SDIO_STA)來判斷命令回應是否已經正確被接收,然后,通過函式SDIO_GetCommandResponse獲取SDIO 命令回應暫存器 (SDIO_RESPCMD) Value來判斷Host接收到的回應命令是否是剛剛發送的命令,最后,通過函式SDIO_GetResponse獲取SDIO 回應 1暫存器 (SDIO_RESP1) SD卡的狀態,

static SD_Error CmdResp1Error(uint8_t cmd)
{
  SD_Error errorstatus = SD_OK;
  uint32_t status;
  uint32_t response_r1;

  status = SDIO->STA;

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

  ...

  /*!< 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 for analysis  */
  response_r1 = SDIO_GetResponse(SDIO_RESP1);

  if ((response_r1 & SD_OCR_ERRORBITS) == SD_ALLZERO)
  {
    return(errorstatus);
  }

  if (response_r1 & SD_OCR_ADDR_OUT_OF_RANGE)
  {
    return(SD_ADDR_OUT_OF_RANGE);
  }

  ...
  
  return(errorstatus);
}

從SD2.0協議里面可以了解到CMD7的response是R1b,R1b和R1功能完全相同,主要獲取的Card Status,


通過邏輯分析儀抓取的波形, Card Status指示SD卡當前狀態為Stand-by 狀態, 如下:

6.SD_EnableWideBusOperation()

通過SD_EnableWideBusOperation(SDIO_BusWide_4b)設定總線寬度為4bit模式,首先需要獲取SCR Register Value(FindSCR())判定SD卡是否支持4bit模式,然后發送ACMD6設定SD卡作業在4bit模式,同時host端STM32也設定為4bit模式,整體的思維導圖如下:

6.1 CMD16:SD_CMD_SET_BLOCKLEN

FindSCR()函式中發送CMD16:SD_CMD_SET_BLOCKLEN來設定SD卡Block Size為8 Bytes

#define SD_CMD_SET_BLOCKLEN                        ((uint8_t)16)

/*!< Set Block Size To 8 Bytes */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)8;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);


實際發送出去波形如下:

然后SD卡處理完后,以R1的形式Response Card Status,波形如下:

6.2 SDIO_DataConfig()

SDIO_DataConfig()設定STM32 SDIO暫存器DLEN和DCTRL資料長度和塊大小為8Bytes,并設定傳輸方向為:SD Card -> Host SDIO

  SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
  SDIO_DataInitStructure.SDIO_DataLength = 8;
  SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_8b;
  SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;
  SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
  SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
  SDIO_DataConfig(&SDIO_DataInitStructure);

6.3 ACMD51:SD_CMD_SD_APP_SEND_SCR

ACMD51:SD_CMD_SD_APP_SEND_SCR主要是讀取配置暫存器 SCR的值,發送完這個命令后R1回傳Card Status,然后在DATA0資料線上回傳SCR的值,

#define SD_CMD_SD_APP_SEND_SCR                     ((uint8_t)51) /*!< For SD Card only */

/*!< Send ACMD51 SD_APP_SEND_SCR with argument as 0 */
SDIO_CmdInitStructure.SDIO_Argument = 0x0;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_APP_SEND_SCR;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp1Error(SD_CMD_SD_APP_SEND_SCR);


實際發送出去的波形如下:

然后SD卡處理完后,以R1的形式Response Card Status,波形如下:

6.4 SDIO_ReadData()

SDIO_ReadData()從SDIO FIFO中獲取DATA0 SD卡回傳的SCR Value:

  while (!(SDIO->STA & (SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR)))
  {
    if (SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET)
    {
      *(tempscr + index) = SDIO_ReadData();
      index++;
    }
  }

在SDIO DATA0上面回傳SCR Value為:0x0235804300000000,波形如下:

SCR Value為:0x0235804300000000對應SCR暫存器的表格如下:

DescriptionFieldWidthValueCell
Type
SCR
Slice
SCR Structure SCR_STRUCTURE40000bR[63:60]
SD Memory Card - Spec. VersionSD_SPEC40010bR[59:56]
data_status_after erasesDATA_STAT_AFTER_ERASE10bR[55:55]
SD Security SupportSD_SECURITY3011bR[54:52]
DAT Bus widths supportedSD_BUS_WIDTHS40101bR[51:48]
reserved-16 R[47:32]
reserved for manufacturer usage-32 R[31:0]
  • SCR_STRUCTURE
  • SD_SPEC
    SD_SPEC描述了SD卡支持SD協議版本號,
  • SD_SECURITY
    SD_SECURITY描述了Security Specification Version版本號,
  • SD_BUS_WIDTHS
    SD_BUS_WIDTHS描述了SDIO總線的寬度,同時支持1bit和4bit,

6.5 ACMD6:SD_CMD_APP_SD_SET_BUSWIDTH

ACMD6:SD_CMD_APP_SD_SET_BUSWIDTH 通過SCR Value判斷SD卡支持4bit總線,并通過AMCD6設定SD卡總線寬度為4bit,

#define SD_CMD_APP_SD_SET_BUSWIDTH                 ((uint8_t)6)  /*!< For SD Card only */

/*!< Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
SDIO_CmdInitStructure.SDIO_Argument = 0x2;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_SD_SET_BUSWIDTH;
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);

errorstatus = CmdResp1Error(SD_CMD_APP_SD_SET_BUSWIDTH);


實際發送出去的波形如下:

6.6 SDIO_Init()

SDIO_Init()配置STM32 SDIO時鐘控制暫存器(SDIO_CLKCR):時鐘為25MHz和總線寬度為4bit模式

/*!< Configure the SDIO peripheral */
SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV; 
SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;
SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_4b;
SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;
SDIO_Init(&SDIO_InitStructure);

Note:到此SD_Init的整個SD卡初始化完成,

7. 參考資料

SDIO參考的資料如下:

下載地址如下:
https://download.csdn.net/download/ZHONGCAI0901/14975835

移植成功的完整代碼下載地址如下:
https://download.csdn.net/download/ZHONGCAI0901/15265756

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/264566.html

標籤:其他

上一篇:抖音為什么這么火

下一篇:硬體學習之路——STM32之TM1638

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more