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

stm32中的SDIO

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

SDIO-SD卡

SD卡結(jié)構(gòu)

物理結(jié)構(gòu)

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

  • 存儲(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)器控制SD卡引腳的輸入輸出
  • SD卡總共有8個(gè)寄存器,用于設(shè)定或表示SD卡信息。

SD卡寄存器列表

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

SDIO總線(xiàn)

SDIO總線(xiàn)拓?fù)?/h3>

SD卡與SDIO接口示意圖

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

推薦一個(gè)單獨(dú)SD總線(xiàn)應(yīng)該連接一個(gè)單獨(dú)的SD卡

SD卡使用9-pin接口通信,其中3根電源線(xiàn)、1根時(shí)鐘線(xiàn)、1根命令線(xiàn)和4根數(shù)據(jù)線(xiàn),具體如下:

? CLK:時(shí)鐘線(xiàn),由SDIO主機(jī)產(chǎn)生,即由STM32控制器輸出;

? CMD:命令控制線(xiàn),SDIO主機(jī)通過(guò)該線(xiàn)發(fā)送命令控制SD卡,如果命令要求SD卡提供應(yīng)答,SD卡也是通過(guò)該線(xiàn)傳輸應(yīng)答信息;

? D0-3:數(shù)據(jù)線(xiàn),傳輸讀寫(xiě)數(shù)據(jù);SD卡可將D0拉低表示忙狀態(tài);

? VDD、VSS1、VSS2:電源和地信號(hào);

SDIO總線(xiàn)

SDIO不管是從主機(jī)控制器向SD卡傳輸,還是SD卡向主機(jī)控制器傳輸都只以CLK時(shí)鐘線(xiàn)的上升沿為有效。

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

開(kāi)始通訊的時(shí)候要發(fā)送一個(gè)起始位"0",最后由一個(gè)停止位"1"停止。

SD通訊一般是主機(jī)發(fā)送一個(gè)命令,從設(shè)備接收到命令后做出響應(yīng)(有些命令沒(méi)有響應(yīng)可能)如果有數(shù)據(jù)傳輸,DATA線(xiàn)也需要用

SDIO總線(xiàn)協(xié)議

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

補(bǔ)充:

  • SD數(shù)據(jù)是以塊(Black)形式傳輸?shù)?,SDHC卡數(shù)據(jù)塊長(zhǎng)度一般為512字節(jié)
  • 數(shù)據(jù)塊需要CRC位來(lái)保證數(shù)據(jù)傳輸成功。
  • CRC位由SD卡系統(tǒng)硬件生成。
  • STM32控制器可以控制使用單線(xiàn)或4線(xiàn)傳輸,本開(kāi)發(fā)板(野火指南者)設(shè)計(jì)使用4線(xiàn)傳輸

協(xié)議:

SD數(shù)據(jù)傳輸支持單塊和多塊讀寫(xiě),它們分別對(duì)應(yīng)不同的操作命令,多塊寫(xiě)入還需要使用命令來(lái)停止整個(gè)寫(xiě)入操作。

數(shù)據(jù)寫(xiě)入前需要檢測(cè)SD卡忙狀態(tài),因?yàn)镾D卡在接收到數(shù)據(jù)后編程到存儲(chǔ)區(qū)過(guò)程需要一定操作時(shí)間。SD卡忙狀態(tài)通過(guò)把D0線(xiàn)拉低表示。

常規(guī)數(shù)據(jù)傳輸

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

使用4數(shù)據(jù)線(xiàn)傳輸時(shí),每次傳輸4bit數(shù)據(jù),每根數(shù)據(jù)線(xiàn)都必須有起始位、終止位以及CRC位,CRC位每根數(shù)據(jù)線(xiàn)都要分別檢查,并把檢查結(jié)果匯總?cè)缓笤跀?shù)據(jù)傳輸完后通過(guò)D0線(xiàn)反饋給主機(jī)

寬位數(shù)據(jù)包

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

對(duì)SD卡而言寬位數(shù)據(jù)包發(fā)送方式是針對(duì)SD卡SSR(SD狀態(tài))寄存器內(nèi)容發(fā)送的,SSR寄存器總共有512bit,在主機(jī)發(fā)出ACMD13命令后SD卡將SSR寄存器內(nèi)容通過(guò)DAT線(xiàn)發(fā)送給主機(jī)。

命令

命令格式

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

命令的類(lèi)型

? 無(wú)響應(yīng)廣播命令 (bc),發(fā)送到所有卡,不返回任務(wù)響應(yīng);

? 帶響應(yīng)廣播命令 (bcr),發(fā)送到所有卡,同時(shí)接收來(lái)自所有卡響應(yīng);

? 尋址命令 (ac),發(fā)送到選定卡,DAT 線(xiàn)無(wú)數(shù)據(jù)傳輸;

? 尋址數(shù)據(jù)傳輸命令 (adtc),發(fā)送到選定卡,DAT 線(xiàn)有數(shù)據(jù)傳輸。

在標(biāo)準(zhǔn)中定義了兩種類(lèi)型的通用命令:特定應(yīng)用命令 (ACMD) 和常規(guī)命令 (GEN_CMD)。要使用 SD 卡制造商特定的 ACMD 命令如 ACMD6,需要在發(fā)送該命令之前發(fā)送 CMD55 命令,告知 SD 卡接下來(lái)的命令為特定應(yīng)用命令。CMD55 命令只對(duì)緊接的第一個(gè)命令有效,SD 卡如果檢測(cè)到 CMD55 之后的第一條命令為 ACMD 則執(zhí)行其特定應(yīng)用功能,如果檢測(cè)發(fā)現(xiàn)不是 ACMD 命令,則執(zhí)行標(biāo)準(zhǔn)命令。

命令集

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

七個(gè)響應(yīng)類(lèi)型:

  1. R1 Response (Normal Response): R1響應(yīng)是最基本的響應(yīng),包含一個(gè)字節(jié)的狀態(tài)位,用于指示命令是否成功執(zhí)行。

  2. R1b Response (Normal with Busy): 類(lèi)似于R1,但在命令執(zhí)行完成后,卡會(huì)持續(xù)將忙位(busy)發(fā)送給主機(jī),直到卡準(zhǔn)備好執(zhí)行下一個(gè)命令。

  3. R2 Response (CID or CSD Register Response): 包含兩個(gè)字節(jié)的數(shù)據(jù),用于讀取CID(Card ID)或CSD(Card Specific Data)寄存器內(nèi)容。

  4. R3 Response (OCR Register Response): 包含四個(gè)字節(jié)的數(shù)據(jù),用于讀取OCR(Operating Conditions Register)寄存器內(nèi)容。

  5. R6 Response (Published RCA Response): 包含一個(gè)字節(jié)的狀態(tài)位和一個(gè)字節(jié)的相對(duì)卡地址(RCA),用于獲取卡的相對(duì)地址。

  6. R7 Response (Card Interface Condition Response): 包含一個(gè)字節(jié)的狀態(tài)位和一個(gè)字節(jié)的回應(yīng)信息,用于卡初始化階段。

  7. Data Response (for Data Transfer Commands): 在讀/寫(xiě)數(shù)據(jù)時(shí),卡會(huì)響應(yīng)數(shù)據(jù)響應(yīng),用于指示數(shù)據(jù)是否成功接收。

注意:

  • 短響應(yīng)是 48bit長(zhǎng)度,只有 R2 類(lèi)型是長(zhǎng)響應(yīng),其長(zhǎng)度為 136bit。
  • 除了 R3 類(lèi)型之外,其他響應(yīng)都使用 CRC7 校驗(yàn)來(lái)校驗(yàn),對(duì)于 R2 類(lèi)型是使用 CID 和 CSD 寄存器內(nèi)部 CRC7。

SD卡的操作模式

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

  1. 主 機(jī) 上 電 后, 所 有 卡 處 于 空 閑 狀 態(tài), 包 括 當(dāng) 前 處 于 無(wú) 效 狀 態(tài) 的 卡。
  2. 主 機(jī) 也 可 以 發(fā) 送GO_IDLE_STATE(CMD0) 讓所有卡軟復(fù)位從而進(jìn)入空閑狀態(tài),但當(dāng)前處于無(wú)效狀態(tài)的卡并不會(huì)復(fù)位。
  3. 主機(jī)在開(kāi)始與卡通信前,需要先確定雙方在互相支持的電壓范圍內(nèi)。SD 卡有一個(gè)電壓支持范圍,主機(jī)當(dāng)前電壓必須在該范圍可能才能與卡正常通信。SEND_IF_COND(CMD8) 命令就是用于驗(yàn)證卡接口操作條件的 (主要是電壓支持)??〞?huì)根據(jù)命令的參數(shù)來(lái)檢測(cè)操作條件匹配性,如果卡支持主機(jī)電壓就產(chǎn)生響應(yīng),否則不響應(yīng)。而主機(jī)則根據(jù)響應(yīng)內(nèi)容確定卡的電壓匹配性。CMD8 是 SD卡標(biāo)準(zhǔn) V2.0 版本才有的新命令,所以如果主機(jī)有接收到響應(yīng),可以判斷卡為 V2.0 或更高版本SD 卡。
  4. SD_SEND_OP_COND(ACMD41) 命令可以識(shí)別或拒絕不匹配它的電壓范圍的卡。ACMD41 命令的 VDD 電壓參數(shù)用于設(shè)置主機(jī)支持電壓范圍,卡響應(yīng)會(huì)返回卡支持的電壓范圍。對(duì)于對(duì) CMD8有響應(yīng)的卡,把 ACMD41 命令的 HCS 位設(shè)置為 1,可以測(cè)試卡的容量類(lèi)型,如果卡響應(yīng)的 CCS 位為 1 說(shuō)明為高容量 SD 卡,否則為標(biāo)準(zhǔn)卡??ㄔ陧憫?yīng) ACMD41 之后進(jìn)入準(zhǔn)備狀態(tài),不響應(yīng) ACMD41的卡為不可用卡,進(jìn)入無(wú)效狀態(tài)。ACMD41 是應(yīng)用特定命令,發(fā)送該命令之前必須先發(fā) CMD55。
  5. ALL_SEND_CID(CMD2) 用來(lái)控制所有卡返回它們的卡識(shí)別號(hào) (CID),處于準(zhǔn)備狀態(tài)的卡在發(fā)送CID 之后就進(jìn)入識(shí)別狀態(tài)。
  6. 之后主機(jī)就發(fā)送 SEND_RELATIVE_ADDR(CMD3) 命令,讓卡自己推薦一個(gè)相對(duì)地址 (RCA) 并響應(yīng)命令。這個(gè) RCA 是 16bit 地址,而 CID 是 128bit 地址,使用 RCA簡(jiǎn)化通信??ㄔ诮邮盏?CMD3 并發(fā)出響應(yīng)后就進(jìn)入數(shù)據(jù)傳輸模式,并處于待機(jī)狀態(tài),主機(jī)在獲取所有卡 RCA 之后也進(jìn)入數(shù)據(jù)傳輸模式

數(shù)據(jù)傳輸模式

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

CMD7 用來(lái)選定和取消指定的卡,卡在待機(jī)狀態(tài)下還不能進(jìn)行數(shù)據(jù)通信,因?yàn)榭偩€(xiàn)上可能有多個(gè)卡都是出于待機(jī)狀態(tài),必須選擇一個(gè) RCA 地址目標(biāo)卡使其進(jìn)入傳輸狀態(tài)才可以進(jìn)行數(shù)據(jù)通信。同時(shí)通過(guò) CMD7 命令(選擇卡命令)也可以讓已經(jīng)被選擇的目標(biāo)卡返回到待機(jī)狀態(tài)。數(shù)據(jù)傳輸模式下的數(shù)據(jù)通信都是主機(jī)和目標(biāo)卡之間通過(guò)尋址命令點(diǎn)對(duì)點(diǎn)進(jìn)行的??ㄌ幱趥鬏敔顟B(tài)下可以使用表 SD 部分命令描述 中面向塊的讀寫(xiě)以及擦除命令對(duì)卡進(jìn)行數(shù)據(jù)讀寫(xiě)、擦除。CMD12可以中斷正在進(jìn)行的數(shù)據(jù)通信,讓卡返回到傳輸狀態(tài)。CMD0 和 CMD15 會(huì)中止任何數(shù)據(jù)編程操作,返回卡識(shí)別模式,這可能導(dǎo)致卡數(shù)據(jù)被損壞。

STM32 的 SDIO 功能框圖

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

時(shí)鐘的配置:

SDIO 使用兩個(gè)時(shí)鐘信號(hào),一個(gè)是 SDIO 適配器時(shí)鐘 (SDIOCLK=HCLK=72MHz),另外一個(gè)是 AHB總線(xiàn)時(shí)鐘的二分頻 (HCLK/2,一般為 36MHz)。適配器寄存器和 FIFO 使用 AHB 總線(xiàn)一側(cè)的時(shí)鐘(HCLK/2),控制單元、命令通道和數(shù)據(jù)通道使用 SDIO 適配器一側(cè)的時(shí)鐘 (SDIOCLK)。

SDIO_CK 是 SDIO 接口與 SD 卡用于同步的時(shí)鐘信號(hào)。它使用 SDIOCLK 作為 SDIO_CK 的時(shí)鐘來(lái)源,可以通過(guò)設(shè)置 BYPASS 模式直接得到,這時(shí) SDIO_CK = SDIOCLK=HCLK。若禁止 BYPASS 模式,可以通過(guò)配置時(shí)鐘寄存器的 CLKDIV 位控制分頻因子,即 SDIO_CK=SDIOCLK/(2+CLKDIV)= HCLK/(2+CLKDIV)。

配置時(shí)鐘時(shí)要注意,SD 卡普遍要求 SDIO_CK 時(shí)鐘頻率不能超過(guò) 25MHz。STM32 控制器的 SDIO 是針對(duì) MMC 卡和 SD 卡的主設(shè)備,所以預(yù)留有 8 根數(shù)據(jù)線(xiàn),對(duì)于 SD 卡最多用四根數(shù)據(jù)線(xiàn)。SDIO 適配器是 SD 卡系統(tǒng)主機(jī)部分,是 STM32 控制器與 SD 卡數(shù)據(jù)通信中間設(shè)備。SDIO 適配器由五個(gè)單元組成,分別是控制單元、命令路徑單元、數(shù)據(jù)路徑單元、寄存器單元以及 FIFO。

內(nèi)部適配器

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

控制單元

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

電源管理部件會(huì)在系統(tǒng)斷電和上電階段禁止 SD 卡總線(xiàn)輸出信號(hào)。時(shí)鐘管理部件控制 CLK 線(xiàn)時(shí)鐘信號(hào)生成。一般使用 SDIOCLK 分頻得到。

命令路徑

命令路徑控制命令發(fā)送,并接收卡的響應(yīng)。

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

CPSM 狀態(tài)機(jī)描述圖

STM32 控制器以命令路徑狀態(tài)機(jī) (CPSM) 來(lái)描述 SDIO適配器的狀態(tài)變化,并加入了等待超時(shí)檢測(cè)功能,以便退出永久等待的情況。

由stm32自己控制無(wú)需十分了解

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

數(shù)據(jù)路徑

數(shù)據(jù)路徑部件負(fù)責(zé)與 SD 卡相互數(shù)據(jù)傳輸

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

SD 卡系統(tǒng)數(shù)據(jù)傳輸狀態(tài)轉(zhuǎn)換參考圖數(shù)據(jù)傳輸模式卡狀態(tài)轉(zhuǎn)換 ,SDIO 適配器以數(shù)據(jù)路徑狀態(tài)機(jī)(DPSM) 來(lái)描述 SDIO 適配器狀態(tài)變化情況。并加入了等待超時(shí)檢測(cè)功能,以便退出永久等待情況。發(fā)送數(shù)據(jù)時(shí),DPSM 處于等待發(fā)送 (Wait_S) 狀態(tài),如果數(shù)據(jù) FIFO 不為空,DPSM 變成發(fā)送狀態(tài)并且數(shù)據(jù)路徑部件啟動(dòng)向卡發(fā)送數(shù)據(jù)。接收數(shù)據(jù)時(shí),DPSM 處于等待接收狀態(tài),當(dāng) DPSM 收到起始位時(shí)變成接收狀態(tài),并且數(shù)據(jù)路徑部件開(kāi)始從卡接收數(shù)據(jù)。

DPSM 狀態(tài)機(jī)

stm32 sdio,stm32,嵌入式硬件,單片機(jī)

數(shù)據(jù) FIFO

數(shù)據(jù) FIFO(先進(jìn)先出) 部件是一個(gè)數(shù)據(jù)緩沖器,帶發(fā)送和接收單元??刂破鞯?FIFO 包含寬度為32bit、深度為 32 字的數(shù)據(jù)緩沖器和發(fā)送/接收邏輯。其中 SDIO 狀態(tài)寄存器 (SDIO_STA) 的 TXACT位用于指示當(dāng)前正在發(fā)送數(shù)據(jù),RXACT 位指示當(dāng)前正在接收數(shù)據(jù),這兩個(gè)位不可能同時(shí)為 1。? 當(dāng) TXACT 為 1 時(shí),可以通過(guò) AHB 接口將數(shù)據(jù)寫(xiě)入到傳輸 FIFO。? 當(dāng) RXACT 為 1 時(shí),接收 FIFO 存放從數(shù)據(jù)路徑部件接收到的數(shù)據(jù)。根據(jù) FIFO 空或滿(mǎn)狀態(tài)會(huì)把 SDIO_STA 寄存器位值 1,并可以產(chǎn)生中斷和 DMA 請(qǐng)求。

SDIO結(jié)構(gòu)體

SDIO初始化結(jié)構(gòu)體

 typedef struct {
 uint32_t SDIO_ClockEdge; // 時(shí)鐘沿
 uint32_t SDIO_ClockBypass; // 旁路時(shí)鐘
 uint32_t SDIO_ClockPowerSave; // 節(jié)能模式
 uint32_t SDIO_BusWide; // 數(shù)據(jù)寬度
 uint32_t SDIO_HardwareFlowControl; // 硬件流控制
 uint8_t SDIO_ClockDiv; // 時(shí)鐘分頻
 } SDIO_InitTypeDef;

SDIO 命令初始化結(jié)構(gòu)體

typedef struct {
 uint32_t SDIO_Argument; // 命令參數(shù)
 uint32_t SDIO_CmdIndex; // 命令號(hào)
 uint32_t SDIO_Response; // 響應(yīng)類(lèi)型
 uint32_t SDIO_Wait; // 等待使能
 uint32_t SDIO_CPSM; // 命令路徑狀態(tài)機(jī)
 } SDIO_CmdInitTypeDef;

SDIO 數(shù)據(jù)初始化結(jié)構(gòu)體

typedef struct {
 uint32_t SDIO_DataTimeOut; // 數(shù)據(jù)傳輸超時(shí)
 uint32_t SDIO_DataLength; // 數(shù)據(jù)長(zhǎng)度
 uint32_t SDIO_DataBlockSize; // 數(shù)據(jù)塊大小
 uint32_t SDIO_TransferDir; // 數(shù)據(jù)傳輸方向
 uint32_t SDIO_TransferMode; // 數(shù)據(jù)傳輸模式
 uint32_t SDIO_DPSM; // 數(shù)據(jù)路徑狀態(tài)機(jī)
 } SDIO_DataInitTypeDef;

SD卡的讀寫(xiě)實(shí)驗(yàn)

準(zhǔn)備工作

#include "sdio/sdio_test.h"
#include "./led/bsp_led.h"
#include "./sdio/bsp_sdio_sdcard.h"
#include "./usart/bsp_usart.h"

/* Private typedef -----------------------------------------------------------*/
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;

/* Private define ------------------------------------------------------------*/
#define BLOCK_SIZE            512 /* Block Size in Bytes */

#define NUMBER_OF_BLOCKS      10  /* For Multi Blocks operation (Read/Write) */
#define MULTI_BUFFER_SIZE    (BLOCK_SIZE * NUMBER_OF_BLOCKS)


/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint8_t Buffer_Block_Tx[BLOCK_SIZE], Buffer_Block_Rx[BLOCK_SIZE];
uint8_t Buffer_MultiBlock_Tx[MULTI_BUFFER_SIZE], Buffer_MultiBlock_Rx[MULTI_BUFFER_SIZE];
volatile TestStatus EraseStatus = FAILED, TransferStatus1 = FAILED, TransferStatus2 = FAILED;
SD_Error Status = SD_OK;

/* Private function prototypes -----------------------------------------------*/
static void SD_EraseTest(void);
static void SD_SingleBlockTest(void);
void SD_MultiBlockTest(void);
static void Fill_Buffer(uint8_t *pBuffer, uint32_t BufferLength, uint32_t Offset);
static TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint32_t BufferLength);
static TestStatus eBuffercmp(uint8_t* pBuffer, uint32_t BufferLength);

/* Private functions---------------------------------------------------------*/

void SD_EraseTest(void)

void SD_EraseTest(void)
{  
  /*------------------- Block Erase ------------------------------------------*/
  if (Status == SD_OK)
  {
    /* Erase NumberOfBlocks Blocks of WRITE_BL_LEN(512 Bytes) */
    Status = SD_Erase(0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));
  }

  if (Status == SD_OK)
  {
    Status = SD_ReadMultiBlocks(Buffer_MultiBlock_Rx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);

    /* Check if the Transfer is finished */
    Status = SD_WaitReadOperation();

    /* Wait until end of DMA transfer */
    while(SD_GetStatus() != SD_TRANSFER_OK);
  }

  /* Check the correctness of erased blocks */
  if (Status == SD_OK)
  {
    EraseStatus = eBuffercmp(Buffer_MultiBlock_Rx, MULTI_BUFFER_SIZE);
  }
  
  if(EraseStatus == PASSED)
  {    
		LED_GREEN;
    printf("SD卡擦除測(cè)試成功!\n");
  }
  else
  {
		LED_BLUE;
    printf("SD卡擦除測(cè)試失??!\n");
    printf("溫馨提示:部分SD卡不支持擦除測(cè)試,若SD卡能通過(guò)下面的single讀寫(xiě)測(cè)試,即表示SD卡能夠正常使用。\n");
  }
}
  1. 擦除操作:

    Status = SD_Erase(0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));
    

    這里調(diào)用了SD_Erase函數(shù),擦除了從地址0x00開(kāi)始,總共 BLOCK_SIZE * NUMBER_OF_BLOCKS 大小的數(shù)據(jù)塊。Status 用于存儲(chǔ)函數(shù)執(zhí)行的狀態(tài)。

  2. 讀取操作:

    Status = SD_ReadMultiBlocks(Buffer_MultiBlock_Rx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);
    

    如果擦除操作成功,接下來(lái)進(jìn)行讀取操作。這里調(diào)用了SD_ReadMultiBlocks函數(shù),從地址0x00開(kāi)始讀取 BLOCK_SIZE 大小的數(shù)據(jù)塊,總共讀取 NUMBER_OF_BLOCKS 個(gè)塊。

  3. 等待讀取操作完成:

    Status = SD_WaitReadOperation();
    

    等待讀取操作完成,確保數(shù)據(jù)已被成功讀取。

  4. 檢查擦除的塊的正確性:

    EraseStatus = eBuffercmp(Buffer_MultiBlock_Rx, MULTI_BUFFER_SIZE);
    

    通過(guò)比較讀取的數(shù)據(jù)塊與期望的擦除狀態(tài),判斷擦除是否成功。

  5. 根據(jù)檢查結(jié)果輸出信息:

    if (EraseStatus == PASSED)
    {
        LED_GREEN;
        printf("SD卡擦除測(cè)試成功!\n");
    }
    else
    {
        LED_BLUE;
        printf("SD卡擦除測(cè)試失敗!\n");
        printf("溫馨提示:部分SD卡不支持擦除測(cè)試,若SD卡能通過(guò)下面的single讀寫(xiě)測(cè)試,即表示SD卡能夠正常使用。\n");
    }
    

    根據(jù)擦除測(cè)試的結(jié)果,點(diǎn)亮相應(yīng)的LED并輸出信息。

void SD_MultiBlockTest(void)


{  
  /*--------------- Multiple Block Read/Write ---------------------*/
  /* 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)
  {
		LED_GREEN;
    printf("Multi block 測(cè)試成功!");

  }
  else
  {
		LED_RED;
    printf("Multi block 測(cè)試失敗,請(qǐng)確保SD卡正確接入開(kāi)發(fā)板,或換一張SD卡測(cè)試!");
  }
}

這是一個(gè)多塊數(shù)據(jù)讀寫(xiě)測(cè)試的C語(yǔ)言函數(shù)。讓我解釋一下主要的步驟:

  1. 填充發(fā)送緩沖區(qū):

    Fill_Buffer(Buffer_MultiBlock_Tx, MULTI_BUFFER_SIZE, 0x0);
    

    這里調(diào)用了 Fill_Buffer 函數(shù),用0x0填充了 Buffer_MultiBlock_Tx 緩沖區(qū),該緩沖區(qū)用于發(fā)送數(shù)據(jù)。

  2. 多塊數(shù)據(jù)寫(xiě)操作:

    Status = SD_WriteMultiBlocks(Buffer_MultiBlock_Tx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);
    

    如果填充緩沖區(qū)成功,接下來(lái)進(jìn)行多塊數(shù)據(jù)寫(xiě)入操作。調(diào)用了 SD_WriteMultiBlocks 函數(shù),將填充的數(shù)據(jù)寫(xiě)入從地址0x00開(kāi)始的多個(gè)數(shù)據(jù)塊。

  3. 等待寫(xiě)操作完成:

    Status = SD_WaitWriteOperation();
    while(SD_GetStatus() != SD_TRANSFER_OK);
    

    等待寫(xiě)入操作完成,確保數(shù)據(jù)已成功寫(xiě)入SD卡。

  4. 多塊數(shù)據(jù)讀操作:

    Status = SD_ReadMultiBlocks(Buffer_MultiBlock_Rx, 0x00, BLOCK_SIZE, NUMBER_OF_BLOCKS);
    

    如果寫(xiě)入操作成功,接下來(lái)進(jìn)行多塊數(shù)據(jù)讀取操作。調(diào)用了 SD_ReadMultiBlocks 函數(shù),從地址0x00開(kāi)始讀取多個(gè)數(shù)據(jù)塊。

  5. 等待讀操作完成:

    Status = SD_WaitReadOperation();
    while(SD_GetStatus() != SD_TRANSFER_OK);
    

    等待讀取操作完成,確保數(shù)據(jù)已成功讀取。

  6. 檢查寫(xiě)入的數(shù)據(jù)的正確性:

    TransferStatus2 = Buffercmp(Buffer_MultiBlock_Tx, Buffer_MultiBlock_Rx, MULTI_BUFFER_SIZE);
    

    通過(guò)比較寫(xiě)入的數(shù)據(jù)和讀取的數(shù)據(jù),判斷寫(xiě)入是否成功。

  7. 根據(jù)檢查結(jié)果輸出信息:

    if(TransferStatus2 == PASSED)
    {
        LED_GREEN;
        printf("Multi block 測(cè)試成功!");
    }
    else
    {
        LED_RED;
        printf("Multi block 測(cè)試失敗,請(qǐng)確保SD卡正確接入開(kāi)發(fā)板,或換一張SD卡測(cè)試!");
    }
    

    根據(jù)多塊數(shù)據(jù)讀寫(xiě)測(cè)試的結(jié)果,點(diǎn)亮相應(yīng)的LED并輸出信息。

這段代碼主要用于測(cè)試SD卡的多塊數(shù)據(jù)讀寫(xiě)功能,并通過(guò)比較寫(xiě)入和讀取的數(shù)據(jù)來(lái)驗(yàn)證操作的正確性。如果測(cè)試成功,LED變綠并輸出成功信息,否則LED變紅并輸出失敗信息。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-826163.html

比較函數(shù)和填充函數(shù)補(bǔ)充

/**
  * @brief  Compares two buffers.
  * @param  pBuffer1, pBuffer2: buffers to be compared.
  * @param  BufferLength: buffer's length
  * @retval PASSED: pBuffer1 identical to pBuffer2
  *         FAILED: pBuffer1 differs from pBuffer2
  */
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint32_t BufferLength)
{
  while (BufferLength--)
  {
    if (*pBuffer1 != *pBuffer2)
    {
      return FAILED;
    }

    pBuffer1++;
    pBuffer2++;
  }

  return PASSED;
}

/**
  * @brief  Fills buffer with user predefined data.
  * @param  pBuffer: pointer on the Buffer to fill
  * @param  BufferLength: size of the buffer to fill
  * @param  Offset: first value to fill on the Buffer
  * @retval None
  */
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;
  }
}

/**
  * @brief  Checks if a buffer has all its values are equal to zero.
  * @param  pBuffer: buffer to be compared.
  * @param  BufferLength: buffer's length
  * @retval PASSED: pBuffer values are zero
  *         FAILED: At least one value from pBuffer buffer is different from zero.
  */
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))
    {
      return FAILED;
    }

    pBuffer++;
  }

  return PASSED;
}

/*********************************************END OF FILE**********************/

測(cè)試程序

void SD_Test(void)
{

	LED_BLUE;
  /*------------------------------ SD Init ---------------------------------- */
	/* SD卡使用SDIO中斷及DMA中斷接收數(shù)據(jù),中斷服務(wù)程序位于bsp_sdio_sd.c文件尾*/
  if((Status = SD_Init()) != SD_OK)
  {    
		LED_RED;
    printf("SD卡初始化失敗,請(qǐng)確保SD卡已正確接入開(kāi)發(fā)板,或換一張SD卡測(cè)試!\n");
  }
  else
  {
    printf("SD卡初始化成功!\n");		 
  }
        
  if(Status == SD_OK) 
  {
		LED_BLUE;
    /*擦除測(cè)試*/
    SD_EraseTest();
    
		LED_BLUE;
    /*single block 讀寫(xiě)測(cè)試*/
    SD_SingleBlockTest();
    
		//暫不支持直接多塊讀寫(xiě),多塊讀寫(xiě)可用多個(gè)單塊讀寫(xiě)流程代替
		LED_BLUE;
    /*muti block 讀寫(xiě)測(cè)試*/
    SD_MultiBlockTest();
  }
}

main.c

int main(void)
{									   
	/* 初始化LED燈 */
  LED_GPIO_Config();
	LED_BLUE;	
	/* 初始化獨(dú)立按鍵 */
	Key_GPIO_Config();
  
  /*初始化USART1*/
  USART_Config();
  
	printf("\r\n歡迎使用野火  STM32 開(kāi)發(fā)板。\r\n");	
	
	printf("在開(kāi)始進(jìn)行SD卡基本測(cè)試前,請(qǐng)給開(kāi)發(fā)板插入32G以?xún)?nèi)的SD卡\r\n");			
	printf("本程序會(huì)對(duì)SD卡進(jìn)行 非文件系統(tǒng) 方式讀寫(xiě),會(huì)刪除SD卡的文件系統(tǒng)\r\n");		
	printf("實(shí)驗(yàn)后可通過(guò)電腦格式化或使用SD卡文件系統(tǒng)的例程恢復(fù)SD卡文件系統(tǒng)\r\n");		
	printf("\r\n 但sd卡內(nèi)的原文件不可恢復(fù),實(shí)驗(yàn)前務(wù)必備份SD卡內(nèi)的原文件?。?!\r\n");		
	
	printf("\r\n 若已確認(rèn),請(qǐng)按開(kāi)發(fā)板的KEY1按鍵,開(kāi)始SD卡測(cè)試實(shí)驗(yàn)....\r\n");	
  
  /* Infinite loop */
  while (1)
  {	
		/*按下按鍵開(kāi)始進(jìn)行SD卡讀寫(xiě)實(shí)驗(yàn),會(huì)損壞SD卡原文件*/
		if(	Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON)
		{
			printf("\r\n開(kāi)始進(jìn)行SD卡讀寫(xiě)實(shí)驗(yàn)\r\n");	
		  SD_Test();			
		}
	} 

到了這里,關(guān)于stm32中的SDIO的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(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)文章

  • 【嵌入式學(xué)習(xí)筆記】嵌入式基礎(chǔ)9——STM32啟動(dòng)過(guò)程

    【嵌入式學(xué)習(xí)筆記】嵌入式基礎(chǔ)9——STM32啟動(dòng)過(guò)程

    程序段交叉引用關(guān)系(Section Cross References):描述各文件之間函數(shù)調(diào)用關(guān)系 刪除映像未使用的程序段(Removing Unused input sections from the image):描述工程中未用到被刪除的冗余程序段(函數(shù)/數(shù)據(jù)) 映像符號(hào)表(Image Symbol Table):描述各符號(hào)(程序段/數(shù)據(jù))在存儲(chǔ)器中的地址、類(lèi)

    2024年02月15日
    瀏覽(64)
  • 嵌入式Linux&Android開(kāi)發(fā)-WiFi&BT SDIO調(diào)試

    嵌入式Linux&Android開(kāi)發(fā)-WiFi&BT SDIO調(diào)試

    目錄 ? 一、基本概念 WiFi STA 模式 和 AP 模式 SDIO(Secure Digital I/O) SDIO-WiFi 模塊 二、項(xiàng)目中WiFi說(shuō)明 三、rockchip WiFi啟動(dòng)流程簡(jiǎn)介 WiFi應(yīng)用部分 wpa_supplicant 四、RK WiFi驅(qū)動(dòng)移植流程 4.1 BSP已支持WiFi 4.2 BSP未支持WiFi 五、排查流程 5.1 檢查DTS 5.2 排查DTS對(duì)應(yīng)的GPIO設(shè)置 5.3檢查電壓電平

    2023年04月08日
    瀏覽(47)
  • stm32嵌入式實(shí)驗(yàn)考核

    STM32 實(shí)驗(yàn)考核題目 1. 利用 STM32 小板實(shí)現(xiàn):控制外接 LED 燈每隔 3 秒鐘亮暗變換,同 時(shí)在 PC 機(jī)上顯示 MCU 的計(jì)時(shí)時(shí)間,MCU 的初始時(shí)間由 PC 機(jī) 方設(shè)置。 2. 利用 STM32 小板實(shí)現(xiàn):利用導(dǎo)線(xiàn)外接 GPIO 口模擬 2 個(gè)按鍵輸入, 根據(jù)輸入組合的四種情況,分別控制三色燈四種流水燈效果

    2024年02月03日
    瀏覽(29)
  • 嵌入式 STM32 通訊協(xié)議--MODBUS

    嵌入式 STM32 通訊協(xié)議--MODBUS

    目錄 一、自定義通信協(xié)議 1、協(xié)議介紹 2、網(wǎng)絡(luò)協(xié)議 3、自定義的通信協(xié)議? 二、MODBUS通信協(xié)議 1、概述 2、MODBUS幀結(jié)構(gòu)? 協(xié)議描述 3、MODBUS數(shù)據(jù)模型 ? 4、MODBUS事務(wù)處理的定義 5、MODBUS功能碼? 6、功能碼定義? ?7、MODBUS數(shù)據(jù)鏈路層 8、MODBUS地址規(guī)則? 9、MODBUS幀描述 10、MODBUS兩種

    2024年02月11日
    瀏覽(40)
  • STM32的時(shí)鐘系統(tǒng)(嵌入式學(xué)習(xí))

    STM32的時(shí)鐘系統(tǒng)(嵌入式學(xué)習(xí))

    時(shí)鐘是指用于計(jì)量和同步時(shí)間的裝置或系統(tǒng)。時(shí)鐘是嵌入式系統(tǒng)的脈搏,處理器內(nèi)核在時(shí)鐘驅(qū)動(dòng)下完成指令執(zhí)行,狀態(tài)變換等動(dòng)作,外設(shè)部件在時(shí)鐘的驅(qū)動(dòng)下完成各種工作,例如:串口數(shù)據(jù)的發(fā)送、AD轉(zhuǎn)換、定時(shí)器計(jì)數(shù)等。因此時(shí)鐘對(duì)于計(jì)算機(jī)系統(tǒng)是至關(guān)重要的,通常時(shí)鐘系

    2024年02月16日
    瀏覽(29)
  • 嵌入式——新建STM32工程(標(biāo)準(zhǔn)庫(kù))

    嵌入式——新建STM32工程(標(biāo)準(zhǔn)庫(kù))

    目錄 一、初識(shí)標(biāo)準(zhǔn)庫(kù) 1.CMSIS標(biāo)準(zhǔn)及庫(kù)層級(jí)關(guān)系 2.庫(kù)文件介紹 (1)Libraries文件夾 ①CMSIS文件夾 ②STM32F10x_Std_Periph_Driver文件夾 ③ 在用庫(kù)建立一個(gè)完整的工程時(shí),還需要添加stm32f10x_it.c、 stm32f10x_conf.h 和 system_stm32f10x.c文件 (2)Project文件夾 (3)Utilities文件夾 3.庫(kù)各文件之間的關(guān)

    2024年01月23日
    瀏覽(91)
  • STM32串口通信詳解(嵌入式學(xué)習(xí))

    STM32串口通信詳解(嵌入式學(xué)習(xí))

    時(shí)鐘信號(hào)在電子領(lǐng)域中是指用于同步和定時(shí)電路操作的周期性信號(hào)。它在數(shù)字系統(tǒng)和通信系統(tǒng)中起著至關(guān)重要的作用,用于協(xié)調(diào)各個(gè)組件之間的數(shù)據(jù)傳輸和操作。 時(shí)鐘信號(hào)有以下幾個(gè)重要的方面: 頻率:時(shí)鐘信號(hào)的頻率是指單位時(shí)間內(nèi)信號(hào)周期的數(shù)量。它通常以赫茲(Hz)為

    2024年02月09日
    瀏覽(23)
  • 嵌入式項(xiàng)目分享 stm32智能運(yùn)動(dòng)計(jì)步系統(tǒng) - 物聯(lián)網(wǎng) 嵌入式 單片機(jī)

    嵌入式項(xiàng)目分享 stm32智能運(yùn)動(dòng)計(jì)步系統(tǒng) - 物聯(lián)網(wǎng) 嵌入式 單片機(jī)

    ?? 這兩年開(kāi)始畢業(yè)設(shè)計(jì)和畢業(yè)答辯的要求和難度不斷提升,傳統(tǒng)的畢設(shè)題目缺少創(chuàng)新和亮點(diǎn),往往達(dá)不到畢業(yè)答辯的要求,這兩年不斷有學(xué)弟學(xué)妹告訴學(xué)長(zhǎng)自己做的項(xiàng)目系統(tǒng)達(dá)不到老師的要求。 為了大家能夠順利以及最少的精力通過(guò)畢設(shè),學(xué)長(zhǎng)分享優(yōu)質(zhì)畢業(yè)設(shè)計(jì)項(xiàng)目,今天

    2024年02月20日
    瀏覽(108)
  • STM32的中斷系統(tǒng)詳解(嵌入式學(xué)習(xí))

    STM32的中斷系統(tǒng)詳解(嵌入式學(xué)習(xí))

    中斷是處理器中的一種機(jī)制,用于響應(yīng)和處理突發(fā)事件或緊急事件。當(dāng)發(fā)生中斷時(shí),當(dāng)前正在執(zhí)行的程序會(huì)被暫時(shí)中止,處理器會(huì)跳轉(zhuǎn)到中斷處理程序(也稱(chēng)為中斷服務(wù)例程),對(duì)中斷事件進(jìn)行處理。處理完中斷后,處理器再返回到被中斷的程序繼續(xù)執(zhí)行。 中斷可以分為內(nèi)部

    2024年02月12日
    瀏覽(35)
  • 嵌入式C語(yǔ)言基礎(chǔ)(STM32)

    前言:一條混跡嵌入式3年的老咸魚(yú),想到自己第一次接觸到stm32的庫(kù)函數(shù)時(shí),c語(yǔ)言稀碎,痛不欲生的場(chǎng)景,該文章為萌新指條明路。 位操作在嵌入式中常用于直接對(duì)芯片的寄存器進(jìn)行操作,當(dāng)時(shí)作為初學(xué)者的我看著一臉懵逼,至于為什么這樣修改,下面好好分析一下。 ?一

    2024年02月02日
    瀏覽(22)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包