国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

STM32——SDIO的學(xué)習(xí)(驅(qū)動(dòng)SD卡)(實(shí)戰(zhàn)篇)

這篇具有很好參考價(jià)值的文章主要介紹了STM32——SDIO的學(xué)習(xí)(驅(qū)動(dòng)SD卡)(實(shí)戰(zhàn)篇)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

一、SDIO寄存器

1.1 SDIO電源控制寄存器(SDIO_POWER)

1.2 SDIO時(shí)鐘控制寄存器(SDIO_CLKCR)

1.3 SDIO參數(shù)寄存器(SDIO_ARG)

1.4 SDIO命令寄存器(SDIO_CMD)

1.5 SDIO命令響應(yīng)寄存器(SDIO_RESPCMD)

1.6 SDIO響應(yīng) 1..4 寄存器(SDIO_RESPx)

1.7 SDIO數(shù)據(jù)定時(shí)器寄存器(SDIO_DTIMER)

1.8?SDIO數(shù)據(jù)長(zhǎng)度寄存器(SDIO_DLEN)

1.9 SDIO數(shù)據(jù)控制寄存器(SDIO_DCTRL)

1.10 SDIO數(shù)據(jù)計(jì)數(shù)器寄存器(SDIO_DCOUNT)

1.11 SDIO狀態(tài)寄存器(SDIO_STA)

1.12 SDIO清除中斷寄存器(SDIO_ICR)

1.13 SDIO中斷屏蔽寄存器(SDIO_MASK)

1.14 SDIO FIFO計(jì)數(shù)器寄存器(SDIO_FIFOCNT)

1.15 SDIO數(shù)據(jù)FIFO寄存器(SDIO_FIFO)

1.16 SDIO寄存器映像

二、開(kāi)發(fā)思路

三、具體實(shí)例


書(shū)接上回:

STM32——SDIO的學(xué)習(xí)(驅(qū)動(dòng)SD卡)(理論篇)_宇努力學(xué)習(xí)的博客-CSDN博客

在寫(xiě)程序前在最后了解一下SDIO的寄存器

一、SDIO寄存器

設(shè)備通過(guò)可以在AHB上操作的32位控制寄存器與系統(tǒng)通信。
必須以字(32位)的方式操作這些外設(shè)寄存器。

1.1 SDIO電源控制寄存器(SDIO_POWER)

地址偏移: 0x00
復(fù)位值: 0x0000 0000
sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

注意: 寫(xiě)數(shù)據(jù)后的7個(gè)HCLK時(shí)鐘周期內(nèi),不能寫(xiě)入這個(gè)寄存器.

1.2 SDIO時(shí)鐘控制寄存器(SDIO_CLKCR)


地址偏移: 0x04
復(fù)位值: 0x0000 0000
SDIO_CLKCR寄存器控制SDIO_CK輸出時(shí)鐘
sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO
sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

注意:

1 當(dāng)SD/SDIO卡或多媒體卡在識(shí)別模式, SDIO_CK的頻率必須低于400kHz。
2 當(dāng)所有卡都被賦予了相應(yīng)的地址后,時(shí)鐘頻率可以改變到卡總線允許的最大頻率。
3 寫(xiě)數(shù)據(jù)后的7個(gè)HCLK時(shí)鐘周期內(nèi)不能寫(xiě)入這個(gè)寄存器。對(duì)于SD I/O卡,在讀等待期間可以停
止SDIO_CK,此時(shí)SDIO_CLKCR寄存器不控制SDIO_CK
?

1.3 SDIO參數(shù)寄存器(SDIO_ARG)


地址偏移: 0x08
復(fù)位值: 0x0000 0000
SDIO_ARG寄存器包含32位命令參數(shù),它將作為命令的一部分發(fā)送到卡中。
sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

1.4 SDIO命令寄存器(SDIO_CMD)


地址偏移: 0x0C
復(fù)位值: 0x0000 0000
SDIO_CMD寄存器包含命令索引和命令類(lèi)型位。命令索引是作為命令的一部分發(fā)送到卡中。命
令類(lèi)型位控制命令通道狀態(tài)機(jī)(CPSM)。
?

sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

注意:

1 寫(xiě)數(shù)據(jù)后的7個(gè)HCLK時(shí)鐘周期內(nèi)不能寫(xiě)入這個(gè)寄存器。
2 多媒體卡可以發(fā)送2種響應(yīng): 48位長(zhǎng)的短響應(yīng),或136位長(zhǎng)的長(zhǎng)響應(yīng)。 SD卡和SD I/O卡只能發(fā)
送短響應(yīng),參數(shù)可以根據(jù)響應(yīng)的類(lèi)型而變化,軟件將根據(jù)發(fā)送的命令區(qū)分響應(yīng)的類(lèi)型。 CE-ATA
設(shè)備只發(fā)送短響應(yīng)
?

1.5 SDIO命令響應(yīng)寄存器(SDIO_RESPCMD)


地址偏移: 0x10
復(fù)位值: 0x0000 0000
SDIO_RESPCMD寄存器包含最后收到的命令響應(yīng)中的命令索引。如果傳輸?shù)拿铐憫?yīng)不包含
命令索引(長(zhǎng)響應(yīng)或OCR響應(yīng)),盡管它應(yīng)該包含111111b(響應(yīng)中的保留域值),但RESPCMD域
的內(nèi)容未知。

sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

?sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

1.6 SDIO響應(yīng) 1..4 寄存器(SDIO_RESPx)


地址偏移: 0x14 + 4*(x-1),其中 x = 1..4
復(fù)位值: 0x0000 0000
SDIO_RESP1/2/3/4寄存器包含卡的狀態(tài),即收到響應(yīng)的部分信息。
?sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

1.7 SDIO數(shù)據(jù)定時(shí)器寄存器(SDIO_DTIMER)


地址偏移: 0x24
復(fù)位值: 0x0000 0000
SDIO_DTIMER寄存器包含以卡總線時(shí)鐘周期為單位的數(shù)據(jù)超時(shí)時(shí)間。
一個(gè)計(jì)數(shù)器從SDIO_DTIMER寄存器加載數(shù)值,并在數(shù)據(jù)通道狀態(tài)機(jī)(DPSM)進(jìn)入Wait_R或繁忙
狀態(tài)時(shí)進(jìn)行遞減計(jì)數(shù),當(dāng)DPSM處在這些狀態(tài)時(shí),如果計(jì)數(shù)器減為0,則設(shè)置超時(shí)標(biāo)志。
?sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

注意 在寫(xiě)入數(shù)據(jù)控制寄存器進(jìn)行數(shù)據(jù)傳輸之前,必須先寫(xiě)入數(shù)據(jù)定時(shí)器寄存器和數(shù)據(jù)長(zhǎng)度寄存器。

1.8?SDIO數(shù)據(jù)長(zhǎng)度寄存器(SDIO_DLEN)


地址偏移: 0x28
復(fù)位值: 0x0000 0000
SDIO_DLEN寄存器包含需要傳輸?shù)臄?shù)據(jù)字節(jié)長(zhǎng)度。當(dāng)數(shù)據(jù)傳輸開(kāi)始時(shí),這個(gè)數(shù)值被加載到數(shù)據(jù)
計(jì)數(shù)器中。
?sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO?

注意 對(duì)于塊數(shù)據(jù)傳輸,數(shù)據(jù)長(zhǎng)度寄存器中的數(shù)值必須是數(shù)據(jù)塊長(zhǎng)度(見(jiàn)SDIO_DCTRL)的倍數(shù)。在寫(xiě)
入數(shù)據(jù)控制寄存器進(jìn)行數(shù)據(jù)傳輸之前,必須先寫(xiě)入數(shù)據(jù)定時(shí)器寄存器和數(shù)據(jù)長(zhǎng)度寄存器。

1.9 SDIO數(shù)據(jù)控制寄存器(SDIO_DCTRL)


地址偏移: 0x2C
復(fù)位值: 0x0000 0000
SDIO_DCTRL寄存器控制數(shù)據(jù)通道狀態(tài)機(jī)(DPSM)。
sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO
?sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

注意 寫(xiě)數(shù)據(jù)后的7個(gè)HCLK時(shí)鐘周期內(nèi)不能寫(xiě)入這個(gè)寄存器。
?

1.10 SDIO數(shù)據(jù)計(jì)數(shù)器寄存器(SDIO_DCOUNT)


地址偏移: 0x30
復(fù)位值: 0x0000 0000
當(dāng)DPSM從空閑狀態(tài)進(jìn)入Wait_R或Wait_S狀態(tài)時(shí), SDIO_DCOUNT寄存器從數(shù)據(jù)長(zhǎng)度寄存器加
載數(shù)值(見(jiàn)SDIO_DLEN),在數(shù)據(jù)傳輸過(guò)程中,該計(jì)數(shù)器的數(shù)值遞減直到減為0,然后DPSM進(jìn)入
空閑狀態(tài)并設(shè)置數(shù)據(jù)狀態(tài)結(jié)束標(biāo)志DATAEND。

?sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

注意 只能在數(shù)據(jù)傳輸結(jié)束時(shí)讀這個(gè)寄存器

1.11 SDIO狀態(tài)寄存器(SDIO_STA)


地址偏移: 0x34
復(fù)位值: 0x0000 0000
SDIO_STA是一個(gè)只讀寄存器,它包含兩類(lèi)標(biāo)志:
● 靜態(tài)標(biāo)志(位[23:22、 10:0]):寫(xiě)入SDIO中斷清除寄存器(見(jiàn)SDIO_ICR),可以清除這些位。
● 動(dòng)態(tài)標(biāo)志(位[21:11]):這些位的狀態(tài)變化根據(jù)它們對(duì)應(yīng)的那部分邏輯而變化(例如: FIFO滿
和空標(biāo)志變高或變低隨FIFO的數(shù)據(jù)寫(xiě)入變化)。

sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO?

1.12 SDIO清除中斷寄存器(SDIO_ICR)


地址偏移: 0x38
復(fù)位值: 0x0000 0000
SDIO_ICR是一個(gè)只寫(xiě)寄存器,在對(duì)應(yīng)寄存器位寫(xiě)’1’將清除SDIO_STA狀態(tài)寄存器中的對(duì)應(yīng)位。
?sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO?

?

1.13 SDIO中斷屏蔽寄存器(SDIO_MASK)


地址偏移: 0x3C
復(fù)位值: 0x0000 0000
在對(duì)應(yīng)位置’1’, SDIO_MASK中斷屏蔽寄存器決定哪一個(gè)狀態(tài)位產(chǎn)生中斷。

?sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO?

?sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

1.14 SDIO FIFO計(jì)數(shù)器寄存器(SDIO_FIFOCNT)


地址偏移: 0x48
復(fù)位值: 0x0000 0000
SDIO_FIFOCNT寄存器包含還未寫(xiě)入FIFO或還未從FIFO讀出的數(shù)據(jù)字?jǐn)?shù)目。當(dāng)在數(shù)據(jù)控制寄
存器(SDIO_DCTRL)中設(shè)置了數(shù)據(jù)傳輸使能位DTEN,并且DPSM處于空閑狀態(tài)時(shí), FIFO計(jì)數(shù)
器從數(shù)據(jù)長(zhǎng)度寄存器(見(jiàn)SDIO_DLEN)加載數(shù)值。如果數(shù)據(jù)長(zhǎng)度未與字對(duì)齊(4的倍數(shù)),則最后剩
下的1~3個(gè)字節(jié)被當(dāng)成一個(gè)字處理。
?sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

1.15 SDIO數(shù)據(jù)FIFO寄存器(SDIO_FIFO)


地址偏移: 0x80
復(fù)位值: 0x0000 0000
接收和發(fā)送FIFO是32位的寬度讀或?qū)懸唤M寄存器,它在連續(xù)的32個(gè)地址上包含32個(gè)寄存器,
CPU可以使用FIFO讀寫(xiě)多個(gè)操作數(shù)。
sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

1.16 SDIO寄存器映像


下表是SDIO寄存器的總結(jié)。
?

sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO

sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO?

sdio命令,STM32,stm32,學(xué)習(xí),單片機(jī),嵌入式,SDIO?

二、開(kāi)發(fā)思路

????????略掉。我們按照ST官方文檔來(lái)學(xué)習(xí)。從程序中學(xué)習(xí)他們的開(kāi)發(fā)流程。我覺(jué)得這時(shí)最快的方式。在外面都學(xué)會(huì)了以后開(kāi)創(chuàng)直接的東西的時(shí)候才需要按照基礎(chǔ)知識(shí)到程序的流程。

三、具體實(shí)例

使用之前先來(lái)看看怎么取消初始化。?

/**
  * @brief  DeInitializes the SDIO interface.
  * @param  None
  * @retval None
  */
void SD_LowLevel_DeInit(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
  
  /*!< Disable SDIO Clock */
  SDIO_ClockCmd(DISABLE);
  
  /*!< Set Power State to OFF */
  SDIO_SetPowerState(SDIO_PowerState_OFF);

  /*!< DeInitializes the SDIO peripheral */
  SDIO_DeInit();
  
  /*!< Disable the SDIO AHB Clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO, DISABLE);

  /*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /*!< Configure PD.02 CMD line */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
}

?先關(guān)閉時(shí)鐘和電源。

然后對(duì)SDIO外設(shè)的相關(guān)寄存器進(jìn)行設(shè)置。

/**
  * @brief  Deinitializes the SDIO peripheral registers to their default reset values.
  * @param  None
  * @retval None
  */
void SDIO_DeInit(void)
{
  SDIO->POWER = 0x00000000;
  SDIO->CLKCR = 0x00000000;
  SDIO->ARG = 0x00000000;
  SDIO->CMD = 0x00000000;
  SDIO->DTIMER = 0x00000000;
  SDIO->DLEN = 0x00000000;
  SDIO->DCTRL = 0x00000000;
  SDIO->ICR = 0x00C007FF;
  SDIO->MASK = 0x00000000;
}

其實(shí)就是按照流程給對(duì)應(yīng)寄存器寫(xiě)對(duì)應(yīng)的值。

然后關(guān)閉AHB總線

這時(shí)得注意有沒(méi)有其它設(shè)備使用這條總線。

然后配置使用的引腳模式為浮空輸入。

上面的五個(gè)引腳分別是四根數(shù)據(jù)線和一根時(shí)鐘線。

下面那根是控制線。

看完取消使能再看使能

/**
  * @brief  Initializes the SD Card and put it into StandBy State (Ready for 
  *         data transfer).
  * @param  None
  * @retval None
  */
void SD_LowLevel_Init(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

  /*!< GPIOC and GPIOD Periph clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);

  /*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /*!< Configure PD.02 CMD line */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
  
  /*!< Enable the SDIO AHB Clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO, ENABLE);

  /*!< Enable the DMA2 Clock */
  RCC_AHBPeriphClockCmd(SD_SDIO_DMA_CLK, ENABLE);
}

和取消相反,先使能引腳對(duì)應(yīng)的時(shí)鐘總線。

將四個(gè)數(shù)據(jù)引腳 和時(shí)鐘引腳初始化為復(fù)用推挽輸出。

使能控制引腳和SDIO與DMA的總線。

/**
  * @brief  Allows to erase memory area specified for the given card.
  * @param  startaddr: the start address.
  * @param  endaddr: the end address.
  * @retval SD_Error: SD Card Error code.
  */
SD_Error SD_Erase(uint32_t startaddr, uint32_t endaddr)
{
  SD_Error errorstatus = SD_OK;
  uint32_t delay = 0;
  __IO uint32_t maxdelay = 0;
  uint8_t cardstate = 0;

  /*!< Check if the card coomnd class supports erase command */
  if (((CSD_Tab[1] >> 20) & SD_CCCC_ERASE) == 0)
  {
    errorstatus = SD_REQUEST_NOT_APPLICABLE;
    return(errorstatus);
  }

  maxdelay = 120000 / ((SDIO->CLKCR & 0xFF) + 2);

  if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED)
  {
    errorstatus = SD_LOCK_UNLOCK_FAILED;
    return(errorstatus);
  }

  if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
  {
    startaddr /= 512;
    endaddr /= 512;
  }
  
  /*!< According to sd-card spec 1.0 ERASE_GROUP_START (CMD32) and erase_group_end(CMD33) */
  if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType))
  {
    /*!< Send CMD32 SD_ERASE_GRP_START with argument as addr  */
    SDIO_CmdInitStructure.SDIO_Argument = startaddr;
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_START;
    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_ERASE_GRP_START);
    if (errorstatus != SD_OK)
    {
      return(errorstatus);
    }

    /*!< Send CMD33 SD_ERASE_GRP_END with argument as addr  */
    SDIO_CmdInitStructure.SDIO_Argument = endaddr;
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_ERASE_GRP_END;
    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_ERASE_GRP_END);
    if (errorstatus != SD_OK)
    {
      return(errorstatus);
    }
  }

  /*!< Send CMD38 ERASE */
  SDIO_CmdInitStructure.SDIO_Argument = 0;
  SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ERASE;
  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_ERASE);

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

  for (delay = 0; delay < maxdelay; delay++)
  {}

  /*!< Wait till the card is in programming state */
  errorstatus = IsCardProgramming(&cardstate);
  delay = SD_DATATIMEOUT;
  while ((delay > 0) && (errorstatus == SD_OK) && ((SD_CARD_PROGRAMMING == cardstate) || (SD_CARD_RECEIVING == cardstate)))
  {
    errorstatus = IsCardProgramming(&cardstate);
    delay--;
  }

  return(errorstatus);
}

上面這個(gè)函數(shù)是擦除SD卡某個(gè)區(qū)域的。

下面的函數(shù)是初始化整個(gè)SD卡,并讓其進(jìn)入待機(jī)狀態(tài)。

/**
  * @brief  Initializes the SD Card and put it into StandBy State (Ready for data 
  *         transfer).
  * @param  None
  * @retval SD_Error: SD Card Error code.
  */
SD_Error SD_Init(void)
{
  __IO SD_Error errorstatus = SD_OK;
  
  NVIC_Configuration();
  
  /* SDIO Peripheral Low Level Init */
  SD_LowLevel_Init();

  SDIO_DeInit();

  errorstatus = SD_PowerON();

  if (errorstatus != SD_OK)
  {
    /*!< CMD Response TimeOut (wait for CMDSENT flag) */
    return(errorstatus);
  }

  errorstatus = SD_InitializeCards();

  if (errorstatus != SD_OK)
  {
    /*!< CMD Response TimeOut (wait for CMDSENT flag) */
    return(errorstatus);
  }

  /*!< Configure the SDIO peripheral */
  /*!< SDIO_CK = SDIOCLK / (SDIO_TRANSFER_CLK_DIV + 2) */
  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);

  /*----------------- Read CSD/CID MSD registers ------------------*/
  errorstatus = SD_GetCardInfo(&SDCardInfo);

  if (errorstatus == SD_OK)
  {
    /*----------------- Select Card --------------------------------*/
    errorstatus = SD_SelectDeselect((uint32_t) (SDCardInfo.RCA << 16));
  }

  if (errorstatus == SD_OK)
  {
    errorstatus = SD_EnableWideBusOperation(SDIO_BusWide_4b);
  }  

  return(errorstatus);
}

?對(duì)單個(gè)數(shù)據(jù)塊做讀寫(xiě)測(cè)試。之前學(xué)習(xí)系統(tǒng)移植的時(shí)候,我們了解到SD卡是以512個(gè)字節(jié)為一個(gè)塊的。所以這個(gè)Blocksize就是一個(gè)宏定義的512

/*
 * 函數(shù)名:SD_SingleBlockTest
 * 描述  :	單個(gè)數(shù)據(jù)塊讀寫(xiě)測(cè)試
 * 輸入  :無(wú)
 * 輸出  :無(wú)
 */
void SD_SingleBlockTest(void)
{  
  /* Fill the buffer to send */
  Fill_Buffer(Buffer_Block_Tx, BLOCK_SIZE, 0x320F);

  if (Status == SD_OK)
  {
    /* Write block of 512 bytes on address 0 */
    Status = SD_WriteBlock(Buffer_Block_Tx, 0x00, BLOCK_SIZE);
		
    /* Check if the Transfer is finished */
    Status = SD_WaitWriteOperation();	  
    while(SD_GetStatus() != SD_TRANSFER_OK); 
  }

  if (Status == SD_OK)
  {
    /* Read block of 512 bytes from address 0 */
    Status = SD_ReadBlock(Buffer_Block_Rx, 0x00, BLOCK_SIZE);//讀取數(shù)據(jù)
    /* Check if the Transfer is finished */
    Status = SD_WaitReadOperation();
    while(SD_GetStatus() != SD_TRANSFER_OK);
  }

  /* Check the correctness of written data */
  if (Status == SD_OK)
  {
    TransferStatus1 = Buffercmp(Buffer_Block_Tx, Buffer_Block_Rx, BLOCK_SIZE);	//比較
  }
  
  if(TransferStatus1 == PASSED)
    printf("》單塊讀寫(xiě)測(cè)試成功!\n" );
 
  else  
  	printf("》單塊讀寫(xiě)測(cè)試失??!\n " );  
}

?這里是自己實(shí)現(xiàn)的三個(gè)小函數(shù)。方便在操作時(shí)使用對(duì)應(yīng)功能。

/*
 * 函數(shù)名:Buffercmp
 * 描述  :比較兩個(gè)緩沖區(qū)中的數(shù)據(jù)是否相等
 * 輸入  :-pBuffer1, -pBuffer2 : 要比較的緩沖區(qū)的指針
 *         -BufferLength 緩沖區(qū)長(zhǎng)度
 * 輸出  :-PASSED 相等
 *         -FAILED 不等
 */
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint32_t BufferLength)
{
  while (BufferLength--)
  {
    if (*pBuffer1 != *pBuffer2)
    {
      return FAILED;
    }

    pBuffer1++;
    pBuffer2++;
  }

  return PASSED;
}


/*
 * 函數(shù)名:Fill_Buffer
 * 描述  :在緩沖區(qū)中填寫(xiě)數(shù)據(jù)
 * 輸入  :-pBuffer 要填充的緩沖區(qū)
 *         -BufferLength 要填充的大小
 *         -Offset 填在緩沖區(qū)的第一個(gè)值
 * 輸出  :無(wú) 
 */
void Fill_Buffer(uint8_t *pBuffer, uint32_t BufferLength, uint32_t Offset)
{
  uint16_t index = 0;

  /* Put in global buffer same values */
  for (index = 0; index < BufferLength; index++ )
  {
    pBuffer[index] = index + Offset;
  }
}

/*
 * 函數(shù)名:eBuffercmp
 * 描述  :檢查緩沖區(qū)的數(shù)據(jù)是否為0
 * 輸入  :-pBuffer 要比較的緩沖區(qū)
 *         -BufferLength 緩沖區(qū)長(zhǎng)度        
 * 輸出  :PASSED 緩沖區(qū)的數(shù)據(jù)全為0
 *         FAILED 緩沖區(qū)的數(shù)據(jù)至少有一個(gè)不為0 
 */
TestStatus eBuffercmp(uint8_t* pBuffer, uint32_t BufferLength)
{
  while (BufferLength--)
  {
    /* In some SD Cards the erased state is 0xFF, in others it's 0x00 */
    if ((*pBuffer != 0xFF) && (*pBuffer != 0x00))//擦除后是0xff或0x00
    {
      return FAILED;
    }

    pBuffer++;
  }

  return PASSED;
}

對(duì)多塊讀寫(xiě)如下:

/*
 * 函數(shù)名:SD_MultiBlockTest
 * 描述  :	多數(shù)據(jù)塊讀寫(xiě)測(cè)試
 * 輸入  :無(wú)
 * 輸出  :無(wú)
 */
void SD_MultiBlockTest(void)
{
  /* Fill the buffer to send */
  Fill_Buffer(Buffer_MultiBlock_Tx, MULTI_BUFFER_SIZE, 0x0);

  if (Status == SD_OK)
  {
    /* Write multiple block of many bytes on address 0 */
    Status = SD_WriteMultiBlocks(Buffer_MultiBlock_Tx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);
    /* Check if the Transfer is finished */
    Status = SD_WaitWriteOperation();
    while(SD_GetStatus() != SD_TRANSFER_OK);
  }

  if (Status == SD_OK)
  {
    /* Read block of many bytes from address 0 */
    Status = SD_ReadMultiBlocks(Buffer_MultiBlock_Rx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);
    /* Check if the Transfer is finished */
    Status = SD_WaitReadOperation();
    while(SD_GetStatus() != SD_TRANSFER_OK);
  }

  /* Check the correctness of written data */
  if (Status == SD_OK)
  {
    TransferStatus2 = Buffercmp(Buffer_MultiBlock_Tx, Buffer_MultiBlock_Rx, MULTI_BUFFER_SIZE);
  }
  
  if(TransferStatus2 == PASSED)	  
  	printf("》多塊讀寫(xiě)測(cè)試成功!\n " );

  else 
  	printf("》多塊讀寫(xiě)測(cè)試失?。n  " );  

}

以上驅(qū)動(dòng)程序來(lái)自ST官方驅(qū)動(dòng)庫(kù)。應(yīng)用層測(cè)試demo來(lái)自硬石頭。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-604399.html

到了這里,關(guān)于STM32——SDIO的學(xué)習(xí)(驅(qū)動(dòng)SD卡)(實(shí)戰(zhàn)篇)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • stm32在SDIO模式下SD寫(xiě)入錯(cuò)誤的問(wèn)題

    stm32在SDIO模式下SD寫(xiě)入錯(cuò)誤的問(wèn)題

    1、問(wèn)題描述 使用FAT32 f_write 多次執(zhí)行寫(xiě)操作時(shí),會(huì)報(bào)FR_DISK_ERR錯(cuò)誤,而且是剛開(kāi)始寫(xiě)不報(bào)錯(cuò),寫(xiě)幾次后會(huì)一直報(bào)錯(cuò)。 設(shè)斷點(diǎn)跟蹤到HAL_SD_WriteBlocks中,在調(diào)用SDMMC_CmdWriteMultiBlock時(shí),會(huì)報(bào)SDMMC_ERROR_TX_UNDERRUN,意思 是Transmit FIFO underrun 2、原因分析 如下圖所示,SDMMC開(kāi)始寫(xiě)操作時(shí),首

    2023年04月24日
    瀏覽(31)
  • STM32對(duì)SD卡的讀、寫(xiě)、擦除操作(SDIO模式)(DMA)

    STM32對(duì)SD卡的讀、寫(xiě)、擦除操作(SDIO模式)(DMA)

    對(duì)于STM32操作SD卡來(lái)說(shuō),最重要的就算 初始化 、 寫(xiě)操作 、 讀操作 、 擦除 這幾個(gè)操作了。 對(duì)于初始化部分上一篇文章已經(jīng)分析,本篇就主要分析寫(xiě)、讀、擦除操作。 本篇函數(shù)來(lái)自于 STM32提供的例程 。參考野火的程序進(jìn)行了解釋?zhuān)c野火函數(shù)有些不同。 這幾種函數(shù)完成之后

    2023年04月08日
    瀏覽(20)
  • STM32CubeMX系列09——SDIO(SD卡讀寫(xiě)、SD卡移植FATFS文件系統(tǒng))

    STM32CubeMX系列09——SDIO(SD卡讀寫(xiě)、SD卡移植FATFS文件系統(tǒng))

    ==== 文章匯總(有代碼匯總) ==== 準(zhǔn)備看看這方面的知識(shí),一時(shí)間還沒(méi)不清有什么區(qū)別,先補(bǔ)補(bǔ)課,不需要的跳過(guò)。 參考文章(內(nèi)容來(lái)源):http://www.360doc.com/content/21/1125/22/59057945_1005908465.shtml 主要寫(xiě)這兩個(gè):SD卡、TF卡 共同點(diǎn):SD、TF、MMC都是在MMC基礎(chǔ)上演化發(fā)展不同的規(guī)范,

    2024年02月09日
    瀏覽(25)
  • STM32CubeMX教程28 SDIO - 使用FatFs文件系統(tǒng)讀寫(xiě)SD卡

    正點(diǎn)原子stm32f407探索者開(kāi)發(fā)板V2.4 STM32CubeMX軟件(Version 6.10.0) keil μVision5 IDE(MDK-Arm) ST-LINK/V2驅(qū)動(dòng) 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX軟件配置STM32F407開(kāi)發(fā)板 SDIO使用FatFs中間件讀寫(xiě)4線SD卡,并實(shí)現(xiàn)以輪詢方式讀寫(xiě)SD卡或以DMA方式讀取SD卡 FatFs文件系統(tǒng)相關(guān)知識(shí)請(qǐng)讀者

    2024年02月19日
    瀏覽(30)
  • STM32F4X SDIO(七) 例程講解-SD_InitializeCards & SD_GetCardInfo

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

    本節(jié)例程基于 野火電子的STM32F407的SD卡讀寫(xiě)例程 進(jìn)行講解。上一節(jié)中講解了SD卡上電過(guò)程,這節(jié)將會(huì)講解一下SD卡的初始化過(guò)程,包括 獲取SD卡的CID、CSD和SD卡RCA地址 。 CMD2的作用是 通知所有卡通過(guò)CMD線返回CID值 ,CID值包括 SD卡的識(shí)別號(hào)、制造商ID、OEMID、產(chǎn)品名稱(chēng)、版本號(hào)、

    2024年02月05日
    瀏覽(18)
  • stm32中的SDIO

    stm32中的SDIO

    存儲(chǔ)單元是存儲(chǔ)數(shù)據(jù)部件,存儲(chǔ)單元通過(guò)存儲(chǔ)單元接口與卡控制單元進(jìn)行數(shù)據(jù)傳輸; 電源檢測(cè)單元保證SD卡工作在合適的電壓下,如出現(xiàn)掉電或上狀態(tài)時(shí),它會(huì)使控制單元和存儲(chǔ)單元接口復(fù)位; 卡及接口控制單元控制SD卡的運(yùn)行狀態(tài),它包括有8個(gè)寄存器; 接口驅(qū)動(dòng)器控制S

    2024年02月19日
    瀏覽(21)
  • STM32F4X SDIO(四) SDIO控制器

    STM32F4X SDIO(四) SDIO控制器

    STM32F4X內(nèi)部有一個(gè)SDIO控制器,開(kāi)發(fā)者可以使用這個(gè)控制器跟SD卡進(jìn)行通信,下面就來(lái)簡(jiǎn)單了解一下STM32F4X的SDIO控制器的使用。 下圖為STM32F4X的SDIO控制器框圖,框圖可以分為以下5部分, 適配器寄存器 、 FIFO 、 控制單元 、 命令路徑 、 數(shù)據(jù)路徑 。 SDIO控制器時(shí)鐘 STM32F4X的所有

    2024年02月07日
    瀏覽(39)
  • STM32使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事項(xiàng)

    STM32使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事項(xiàng)

    以STM32F429為例: 1、SDIO配置 配置為4bit模式,此配置不是最終配置,后面會(huì)在代碼進(jìn)行修改。 2、Fatfs配置 Set Defines 選項(xiàng)中的配置可以默認(rèn),最重要注意Advanced Setting 選擇中的配置,如下 該界面配置默認(rèn)Use dma template是默認(rèn)使能的 ,并且不可以選擇,只能選擇使能,所以需要使

    2024年02月11日
    瀏覽(31)
  • SDIO讀寫(xiě)SD卡速度有多快?

    SDIO讀寫(xiě)SD卡速度有多快?

    前兩天測(cè)試了SPI方式讀寫(xiě)SD卡的速度《SPI方式讀寫(xiě)SD卡速度測(cè)試》,今天來(lái)測(cè)試一下SDIO方式的讀寫(xiě)速度。 測(cè)試條件: 單片機(jī):STM32F407VET6 編譯環(huán)境:MDK 5.30+HAL庫(kù) SD卡:閃迪32GB/64GB TF卡 文件系統(tǒng):FatFS R0.12c 之前測(cè)試中說(shuō)過(guò)了,非DMA方式速度和資源利用率都不如DMA方式,所以今

    2024年02月02日
    瀏覽(34)
  • K_A12_014 基于STM32等單片機(jī)驅(qū)動(dòng)S12SD紫外線傳感器模塊 串口與OLED0.96雙顯示

    K_A12_014 基于STM32等單片機(jī)驅(qū)動(dòng)S12SD紫外線傳感器模塊 串口與OLED0.96雙顯示

    注:PCF8591為8位ADC通過(guò)計(jì)算后分辨率會(huì)相對(duì)不是很理想 建議用10位及其以上ADC模塊或者用STM32 具體計(jì)算公式可參考文檔手冊(cè)中CJMCU-S12D-test-arduino.txt文件 單片機(jī)型號(hào) 測(cè)試條件 模塊名稱(chēng) 代碼功能 STC89C52RC 晶振11.0592M S12SD紫外線傳感器模塊 STC89C52RC采集S12SD紫外線傳感器模塊參數(shù)

    2024年02月05日
    瀏覽(22)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包