在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

第二十五章 SDIO——SD卡讀寫測試

W55MH32 ? 來源:W55MH32 ? 作者:W55MH32 ? 2025-06-20 14:01 ? 次閱讀

單芯片解決方案,開啟全新體驗——W55MH32 高性能以太網單片機

W55MH32是WIZnet重磅推出的高性能以太網單片機,它為用戶帶來前所未有的集成化體驗。這顆芯片將強大的組件集于一身,具體來說,一顆W55MH32內置高性能Arm? Cortex-M3核心,其主頻最高可達216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲與數據處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協議棧、內置MAC以及PHY,擁有獨立的32KB以太網收發緩存,可供8個獨立硬件socket使用。如此配置,真正實現了All-in-One解決方案,為開發者提供極大便利。

在封裝規格上,W55MH32 提供了兩種選擇:QFN100和QFN68。

W55MH32L采用QFN100封裝版本,尺寸為12x12mm,其資源豐富,專為各種復雜工控場景設計。它擁有66個GPIO、3個ADC、12通道DMA、17個定時器、2個I2C、5個串口、2個SPI接口(其中1個帶I2S接口復用)、1個CAN、1個USB2.0以及1個SDIO接口。如此豐富的外設資源,能夠輕松應對工業控制中多樣化的連接需求,無論是與各類傳感器、執行器的通信,還是對復雜工業協議的支持,都能游刃有余,成為復雜工控領域的理想選擇。 同系列還有QFN68封裝的W55MH32Q版本,該版本體積更小,僅為8x8mm,成本低,適合集成度高的網關模組等場景,軟件使用方法一致。更多信息和資料請進入網站或者私信獲取。

此外,本W55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應用,涵蓋TCP SSL、HTTP SSL以及 MQTT SSL等,為網絡通信安全再添保障。

為助力開發者快速上手與深入開發,基于W55MH32L這顆芯片,WIZnet精心打造了配套開發板。開發板集成WIZ-Link芯片,借助一根USB C口數據線,就能輕松實現調試、下載以及串口打印日志等功能。開發板將所有外設全部引出,拓展功能也大幅提升,便于開發者全面評估芯片性能。

若您想獲取芯片和開發板的更多詳細信息,包括產品特性、技術參數以及價格等,歡迎訪問官方網頁,我們期待與您共同探索W55MH32的無限可能。

wKgZPGgbOfaANhwzACodXd3sVzg463.png

第二十五章 SDIO——SD卡讀寫測試

本章參考資料:《W55MH32參考手冊》、SD簡易規格文件 《Physical Layer Simplified SpecificationV2.0》(版本號:2.00)。

閱讀本章內容之前,建議先閱讀SD簡易規格文件。

1 SDIO簡介

SD卡(Secure Digital Memory Card)在我們生活中已經非常普遍了,控制器對SD卡進行讀寫通信操作一般有兩種通信接口可選, 一種是SPI接口,另外一種就是SDIO接口。SDIO全稱是安全數字輸入/輸出接口,多媒體卡(MMC)、SD卡、SD I/O卡都有SDIO接口。 W55MH32系列控制器有一個SDIO主機接口,它可以與MMC卡、SD卡、SD I/O卡以及CE-ATA設備進行數據傳輸。MMC卡可以說是SD卡的前身, 現階段已經用得很少。SD I/O卡本身不是用于存儲的卡,它是指利用SDIO傳輸協議的一種外設。比如Wi-Fi Card, 它主要是提供Wi-Fi功能,有些Wi-Fi模塊是使用串口或者SPI接口進行通信的,但Wi-Fi SDIO Card是使用SDIO接口進行通信的。 并且一般設計SD I/O卡是可以插入到SD的插槽。CE-ATA是專為輕薄筆記本硬盤設計的硬盤高速通訊接口。

多媒體卡協會網站www.mmca.org中提供了有MMCA技術委員會發布的多媒體卡系統規范。

SD卡協會網站www.sdcard.org中提供了SD存儲卡和SDIO卡系統規范。

CE-ATA工作組網站www.ce-ata.org中提供了CE_ATA系統規范。

隨之科技發展,SD卡容量需求越來越大,SD卡發展到現在也是有幾個版本的, 關于SDIO接口的設備整體概括見下圖,SDIO接口的設備 :

wKgZPGgxPu6AQ_U_AAE7CuhOvpo937.png

關于SD卡和SD I/O部分內容可以在SD協會網站獲取到詳細的介紹,比如各種SD卡尺寸規則、讀寫速度標示方法、應用擴展等等信息。

本章內容針對SD卡使用講解,對于其他類型卡的應用可以參考相關系統規范實現,所以對于控制器中針對其他類型卡的內容可能在本章中簡單提及或者被忽略, 本章內容不區分SDIO和SD卡這兩個概念。即使目前SD協議提供的SD卡規范版本最新是4.01版本,但W55MH32系列控制器只支持SD卡規范版本2.0, 即只支持標準容量SD和高容量SDHC標準卡,不支持超大容量SDXC標準卡,所以可以支持的最高卡容量是32GB。

2 SD卡物理結構

一張SD卡包括有存儲單元、存儲單元接口、電源檢測、卡及接口控制器和接口驅動器5個部分,見下圖,SD卡物理結構。 存儲單元是存儲數據部件,存儲單元通過存儲單元接口與卡控制單元進行數據傳輸;電源檢測單元保證SD卡工作在合適的電壓下, 如出現掉電或上狀態時,它會使控制單元和存儲單元接口復位;卡及接口控制單元控制SD卡的運行狀態,它包括有8個寄存器;接口驅動器控制SD卡引腳的輸入輸出。

SD卡總共有8個寄存器,用于設定或表示SD卡信息,參考表 SD卡寄存器 。這些寄存器只能通過對應的命令訪問, 對SD卡進行控制操作并不是像操作控制器GPIO相關寄存器那樣一次讀寫一個寄存器的,它是通過命令來控制, SDIO定義了64個命令,每個命令都有特殊意義,可以實現某一特定功能,SD卡接收到命令后, 根據命令要求對SD卡內部寄存器進行修改,程序控制中只需要發送組合命令就可以實現SD卡的控制以及讀寫操作。

名稱 bit 寬度 描述
CID 128 卡識別號 (Card identification number):用來識別的卡的個體號碼 (唯一的)
RCA 16 相對地址 (Relative card address):卡的本地系統地址,初始化時,動態地由卡建議,主機核準。
DSR 16 驅動級寄存器 (Driver Stage Register):配置卡的輸出驅動
CSD 128 卡的特定數據 (Card Specific Data):卡的操作條件信息
SCR 64 SD 配置寄存器 (SD Configuration Register):SD 卡特殊特性信息
OCR 32 操作條件寄存器 (Operation conditions register)
SSR 512 SD 狀態 (SD Status):SD 卡專有特征的信息
CSR 32 卡狀態 (Card Status):卡狀態信息

每個寄存器位的含義可以參考SD簡易規格文件《Physical Layer Simplified Specification V2.0》第5章內容。

3 SDIO總線

3.1 總線拓撲

SD卡一般都支持SDIO和SPI這兩種接口,本章內容只介紹SDIO接口操作方式,如果需要使用SPI操作方式可以參考SPI相關章節。 另外,W55MH32系列控制器的SDIO是不支持SPI通信模式的,如果需要用到SPI通信只能使用SPI外設。

SD卡總線拓撲參考圖 SD卡總線拓撲 。雖然可以共用總線, 但不推薦多卡槽共用總線信號,要求一個單獨SD總線應該連接一個單獨的SD卡。

wKgZPGgxPu-AaYjZAAIajZGlYjk872.png

SD卡使用9-pin接口通信,其中3根電源線、1根時鐘線、1根命令線和4根數據線,具體說明如下:

CLK:時鐘線,由SDIO主機產生,即由W55MH32控制器輸出;

CMD:命令控制線,SDIO主機通過該線發送命令控制SD卡,如果命令要求SD卡提供應答(響應),SD卡也是通過該線傳輸應答信息;

D0-3:數據線,傳輸讀寫數據;SD卡可將D0拉低表示忙狀態;

VDD、VSS1、VSS2:電源和地信號。

在之前的I2C以及SPI章節都有詳細講解了對應的通信時序,實際上,SDIO的通信時序簡單許多,SDIO不管是從主機控制器向SD卡傳輸, 還是SD卡向主機控制器傳輸都只以CLK時鐘線的上升沿為有效。SD卡操作過程會使用兩種不同頻率的時鐘同步數據,一個是識別卡階段時鐘頻率FOD, 最高為400kHz,另外一個是數據傳輸模式下時鐘頻率FPP,默認最高為25MHz,如果通過相關寄存器配置使SDIO工作在高速模式,此時數據傳輸模式最高頻率為50MHz。

對于W55MH32控制器只有一個SDIO主機,所以只能連接一個SDIO設備, 開發板上集成了一個Micro SD卡槽和SDIO接口的WiFi模塊,要求只能使用其中一個設備。 SDIO接口的WiFi模塊一般集成有使能線,如果需要用到SD卡需要先控制該使能線禁用WiFi模塊。

3.2 總線協議

SD總線通信是基于命令和數據傳輸的。通訊由一個起始位(“0”),由一個停止位(“1”)終止。SD通信一般是主機發送一個命令(Command), 從設備在接收到命令后作出響應(Response),如有需要會有數據(Data)傳輸參與。

SD總線的基本交互是命令與響應交互,見下圖,命令與響應交互:

wKgZPGgxPu2AGGzCAACeyVh1GpI741.png

SD數據是以塊(Black)形式傳輸的,SDHC卡數據塊長度一般為512字節,數據可以從主機到卡, 也可以是從卡到主機。數據塊需要CRC位來保證數據傳輸成功。CRC位由SD卡系統硬件生成。 W55MH32控制器可以控制使用單線或4線傳輸,本開發板設計使用4線傳輸。圖 多塊寫入操作 為主機向SD卡寫入數據塊操作示意。

wKgZPGgxPu6AfK7qAAFbqsfzqE0436.png

SD數據傳輸支持單塊和多塊讀寫,它們分別對應不同的操作命令,多塊寫入還需要使用命令來停止整個寫入操作。 數據寫入前需要檢測SD卡忙狀態,因為SD卡在接收到數據后編程到存儲區過程需要一定操作時間。SD卡忙狀態通過把D0線拉低表示。

數據塊讀操作與之類似,只是無需忙狀態檢測。

使用4數據線傳輸時,每次傳輸4bit數據,每根數據線都必須有起始位、終止位以及CRC位,CRC位每根數據線都要分別檢查,并把檢查結果匯總然后在數據傳輸完后通過D0線反饋給主機。

SD卡數據包有兩種格式,一種是常規數據(8bit寬),它先發低字節再發高字節,而每個字節則是先發高位再發低位,4線傳輸示意如圖 8位寬數據包傳輸 。

wKgZPGgxPu2AWeP5AADDkIk2rN0747.png

4線同步發送,每根線發送一個字節的其中兩個位,數據位在四線順序排列發送,DAT3數據線發較高位,DAT0數據線發較低位。

另外一種數據包發送格式是寬位數據包格式,對SD卡而言寬位數據包發送方式是針對SD卡SSR(SD狀態)寄存器內容發送的, SSR寄存器總共有512bit,在主機發出ACMD13命令后SD卡將SSR寄存器內容通過DAT線發送給主機。寬位數據包格式示意見圖,寬位數據包傳輸:

wKgZO2gxPu2ANI7VAACaxgk-7Aw249.png

3.3 命令

SD命令由主機發出,以廣播命令和尋址命令為例,廣播命令是針對與SD主機總線連接的所有從設備發送的,尋址命令是指定某個地址設備進行命令傳輸。

3.3.1 命令格式

SD命令格式固定為48bit,都是通過CMD線連續傳輸的(數據線不參與),見下圖,SD命令格式:

wKgZO2gxPu2AZYNYAACHOT62tnE956.png

SD命令的組成如下:

起始位和終止位:命令的主體包含在起始位與終止位之間,它們都只包含一個數據位,起始位為0,終止位為1。

傳輸標志:用于區分傳輸方向,該位為1時表示命令,方向為主機傳輸到SD卡,該位為0時表示響應,方向為SD卡傳輸到主機。

命令主體內容包括命令、地址信息/參數和CRC校驗三個部分。

命令號:它固定占用6bit,所以總共有64個命令(代號:CMD0~CMD63),每個命令都有特定的用途, 部分命令不適用于SD卡操作,只是專門用于MMC卡或者SD I/O卡。

地址/參數:每個命令有32bit地址信息/參數用于命令附加內容,例如,廣播命令沒有地址信息, 這32bit用于指定參數,而尋址命令這32bit用于指定目標SD卡的地址。

CRC7校驗:長度為7bit的校驗位用于驗證命令傳輸內容正確性, 如果發生外部干擾導致傳輸數據個別位狀態改變將導致校準失敗,也意味著命令傳輸失敗,SD卡不執行命令。

3.3.2 命令類型

SD命令有4種類型:

無響應廣播命令(bc),發送到所有卡,不返回任務響應;

帶響應廣播命令(bcr),發送到所有卡,同時接收來自所有卡響應;

尋址命令(ac),發送到選定卡,DAT線無數據傳輸;

尋址數據傳輸命令(adtc),發送到選定卡,DAT線有數據傳輸。

另外,SD卡主機模塊系統旨在為各種應用程序類型提供一個標準接口。在此環境中,需要有特定的客戶/應用程序功能。為實現這些功能, 在標準中定義了兩種類型的通用命令:特定應用命令(ACMD)和常規命令(GEN_CMD)。要使用SD卡制造商特定的ACMD命令如ACMD6, 需要在發送該命令之前發送CMD55命令,告知SD卡接下來的命令為特定應用命令。CMD55命令只對緊接的第一個命令有效, SD卡如果檢測到CMD55之后的第一條命令為ACMD則執行其特定應用功能,如果檢測發現不是ACMD命令,則執行標準命令。

3.3.3 命令描述

SD卡系統的命令被分為多個類,每個類支持一種“卡的功能設置”。表 SD部分命令描述 列舉了SD卡部分命令信息, 更多詳細信息可以參考SD簡易規格文件說明,表中填充位和保留位都必須被設置為0。

雖然沒有必須完全記住每個命令詳細信息,但越熟悉命令對后面編程理解非常有幫助。

命令序號 類型 參數 響應 縮寫 描述
CMD0 bc [31:0] 填充位 -- GO_IDLE_STATE 復位所有的卡到 idle 狀態。
CMD2 bcr [31:0] 填充位 R2 ALL_SEND_CID 通知所有卡通過 CMD 線返回 CID 值。
CMD3 bcr [31:0] 填充位 R6 SEND_RELATIVE_ADDR 通知所有卡發布新 RCA。
CMD4 bc [31:16]DSR[15:0]
填充位
-- SET_DSR 編程所有卡的 DSR。
CMD7 ac [31:16]RCA[15:0]
填充位
R1b SELECT/DESELECT_CARD 選擇 / 取消選擇 RCA 地址卡。
CMD8 bcr [31:12] 保留位
[11:8] VHS [7:0] 檢查模式
R7 SEND_IF_COND 發送 SD 卡接口條件,包含主機支持的電壓信息,并詢問卡是否支持。
CMD9 ac [31:16]RCA[15:0]
填充位
R2 SEND_CSD 選定卡通過 CMD 線發送 CSD 內容
CMD10 ac [31:16]RCA[15:0]
填充位
R2 SEND_CID 選定卡通過 CMD 線發送 CID 內容
CMD12 ac [31:0] 填充位 R1b STOP_TRANSMISSION 強制卡停止傳輸
CMD13 ac [31:16]RCA[15:0]
填充位
R1 SEND_STATUS 選定卡通過 CMD 線發送它狀態寄存器
CMD15 ac [31:16]RCA[15:0]
填充位
-- GO_INACTIVE_STATE 使選定卡進入 “inactive” 狀態
面向塊的讀操作 (Class 2)
CMD16 ac [31:0] 塊長度填充位 R1 SET_BLOCK_LEN 對于標準 SD 卡,設置塊命令的長度,對于 SDHC 卡塊命令長度固定為 512 字節。
CMD17 adtc [31:0] 數據地址 R1 READ_SINGLE_BLOCK 對于標準卡,讀取 SEL_BLOCK_LEN 長度字節的塊;對于 SDHC 卡,讀取 512 字節的塊。
CMD18 adtc [31:0] 數據地址 R1 READ_MULTIPLE_BLOCK 連續從 SD 卡讀取數據塊,直到被 CMD12 中斷。塊長度同 CMD17。
面向塊的寫操作 (Class 4)
CMD24 adtc [31:0] 數據地址 R1 WRITE_BLOCK 對于標準卡,寫入 SEL_BLOCK_LEN 長度字節的塊;對于 SDHC 卡,寫入 512 字節的塊。
CMD25 adtc [31:0] 數據地址 R1 WRITE_MULTIPLE_BLOCK 連續向 SD 卡寫入數據塊,直到被 CMD12 中斷。每塊長度同 CMD17。
CMD27 adtc [31:0] 填充位 R1 PROGRAM_CSD 對 CSD 的可編程位進行編程
擦除命令 (Class 5)
CMD32 ac [31:0] 數據地址 R1 ERASE_WR_BLK_START 設置擦除的起始塊地址
CMD33 ac [31:0] 數據地址 R1 ERASE_WR_BLK_END 設置擦除的結束塊地址
CMD38 ac [31:0] 填充位 R1b ERASE 擦除預先選定的塊
加鎖命令 (Class 7)
CMD42 adtc [31:0] 保留 R1 LOCK_UNLOCK 加鎖 / 解鎖 SD 卡
特定應用命令 (Class 8)
CMD55 ac [31:16]RCA[15:0]
填充位
R1 APP_CMD 指定下個命令為特定應用命令,不是標準命令
CMD56 adtc [31:1] 填充位 [0] 讀 / 寫 R1 GEN_CMD 通用命令,或特定應用命令中用于傳輸數據塊,最低位為 1 表示讀數據,0 表示寫數據
SD 卡特定應用命令
ACMD6 ac [31:2] 填充位
[1:0] 總線寬度
R1 SET_BUS_WIDTH 定義數據總線寬度 ('00'=1bit,'10'=4bit)。
ACMD13 adtc [31:0] 填充位 R1 SD_STATUS 發送 SD 狀態
ACMD41 Bcr [32] 保留位
[30]HCS(OCR[30])
[29:24] 保留位
[23:0] VDD 電壓
(OCR[23:0])
R3 SD_SEND_OP_COND 主機要求卡發送支持信息 (HCS) 和 OCR 寄存器內容。
ACMD51 adtc [31:0] 填充位 R1 SEND_SCR 讀取配置寄存器 SCR

3.4 響應

響應由SD卡向主機發出,部分命令要求SD卡作出響應,這些響應多用于反饋SD卡的狀態。SDIO總共有7個響應類型(代號:R1~R7), 其中SD卡沒有R4、R5類型響應。特定的命令對應有特定的響應類型,比如當主機發送CMD3命令時,可以得到響應R6。與命令一樣, SD卡的響應也是通過CMD線連續傳輸的。根據響應內容大小可以分為短響應和長響應。短響應是48bit長度, 只有R2類型是長響應,其長度為136bit。各個類型響應具體情況如表 SD卡響應類型 。

除了R3類型之外,其他響應都使用CRC7校驗來校驗,對于R2類型是使用CID和CSD寄存器內部CRC7。

wKgZO2gxPu-AMuDmAAL5L-Dwg4g732.png

4 SD卡的操作模式及切換

4.1 SD卡的操作模式

SD卡有多個版本,W55MH32控制器目前最高支持《Physical Layer Simplified Specification V2.0》定義的SD卡,W55MH32控制器對SD卡進行數據讀寫之前需要識別卡的種類:V1.0標準卡、V2.0標準卡、V2.0高容量卡或者不被識別卡。

SD卡系統(包括主機和SD卡)定義了兩種操作模式:卡識別模式和數據傳輸模式。在系統復位后,主機處于卡識別模式, 尋找總線上可用的SDIO設備;同時,SD卡也處于卡識別模式,直到被主機識別到,即當SD卡接收到SEND_RCA(CMD3)命令后, SD卡就會進入數據傳輸模式,而主機在總線上所有卡被識別后也進入數據傳輸模式。在每個操作模式下, SD卡都有幾種狀態,參考表 SD卡狀態與操作模式 ,通過命令控制實現卡狀態的切換。

wKgZPGgxPu-AaYjZAAIajZGlYjk872.png

4.2 卡識別模式

在卡識別模式下,主機會復位所有處于“卡識別模式”的SD卡,確認其工作電壓范圍,識別SD卡類型, 并且獲取SD卡的相對地址(卡相對地址較短,便于尋址)。在卡識別過程中,要求SD卡工作在識別時鐘頻率FOD的狀態下。 卡識別模式下SD卡狀態轉換如圖 卡識別模式狀態轉換圖 。

wKgZO2gxPu-AUb0uAAIJ5c6JtnE745.png

主機上電后,所有卡處于空閑狀態,包括當前處于無效狀態的卡。主機也可以發送GO_IDLE_STATE(CMD0)讓所有卡軟復位從而進入空閑狀態,但當前處于無效狀態的卡并不會復位。

主機在開始與卡通信前,需要先確定雙方在互相支持的電壓范圍內。SD卡有一個電壓支持范圍,主機當前電壓必須在該范圍可能才能與卡正常通信。 SEND_IF_COND(CMD8)命令就是用于驗證卡接口操作條件的(主要是電壓支持)??〞鶕畹膮祦頇z測操作條件匹配性,如果卡支持主機電壓就產生響應, 否則不響應。而主機則根據響應內容確定卡的電壓匹配性。CMD8是SD卡標準V2.0版本才有的新命令,所以如果主機有接收到響應,可以判斷卡為V2.0或更高版本SD卡。

SD_SEND_OP_COND(ACMD41)命令可以識別或拒絕不匹配它的電壓范圍的卡。ACMD41命令的VDD電壓參數用于設置主機支持電壓范圍,卡響應會返回卡支持的電壓范圍。 對于對CMD8有響應的卡,把ACMD41命令的HCS位設置為1,可以測試卡的容量類型,如果卡響應的CCS位為1說明為高容量SD卡,否則為標準卡。 卡在響應ACMD41之后進入準備狀態,不響應ACMD41的卡為不可用卡,進入無效狀態。ACMD41是應用特定命令,發送該命令之前必須先發CMD55。

ALL_SEND_CID(CMD2)用來控制所有卡返回它們的卡識別號(CID),處于準備狀態的卡在發送CID之后就進入識別狀態。之后主機就發送

SEND_RELATIVE_ADDR(CMD3)命令, 讓卡自己推薦一個相對地址(RCA)并響應命令。這個RCA是16bit地址,而CID是128bit地址,使用RCA簡化通信??ㄔ诮邮盏紺MD3并發出響應后就進入數據傳輸模式, 并處于待機狀態,主機在獲取所有卡RCA之后也進入數據傳輸模式。

4.3 數據傳輸模式

只有SD卡系統處于數據傳輸模式下才可以進行數據讀寫操作。數據傳輸模式下可以將主機SD時鐘頻率設置為FPP,默認最高為25MHz, 頻率切換可以通過CMD4命令來實現。數據傳輸模式下,SD卡狀態轉換過程見圖 數據傳輸模式卡狀態轉換 。

wKgZO2gxPvCAahU6AAJAX4PY334845.png

CMD7用來選定和取消指定的卡,卡在待機狀態下還不能進行數據通信,因為總線上可能有多個卡都是出于待機狀態, 必須選擇一個RCA地址目標卡使其進入傳輸狀態才可以進行數據通信。同時通過CMD7命令也可以讓已經被選擇的目標卡返回到待機狀態。

數據傳輸模式下的數據通信都是主機和目標卡之間通過尋址命令點對點進行的。 卡處于傳輸狀態下可以使用表 SD部分命令描述 中面向塊的讀寫以及擦除命令對卡進行數據讀寫、擦除。 CMD12可以中斷正在進行的數據通信,讓卡返回到傳輸狀態。CMD0和CMD15會中止任何數據編程操作, 返回卡識別模式,這可能導致卡數據被損壞。

5 W55MH32的SDIO功能框圖

W55MH32控制器有一個SDIO,由兩部分組成:SDIO適配器和AHB接口,見下圖,SDIO功能框圖。SDIO適配器提供SDIO主機功能, 可以提供SD時鐘、發送命令和進行數據傳輸。AHB接口用于控制器訪問SDIO適配器寄存器并且可以產生中斷和DMA請求信號。

wKgZPGgxPu2AAfx8AACs0B6o7mY703.png

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

SDIO_CK是SDIO接口與SD卡用于同步的時鐘信號。它使用SDIOCLK作為SDIO_CK的時鐘來源, 可以通過設置BYPASS模式直接得到,這時SDIO_CK = SDIOCLK=HCLK。若禁止BYPASS模式, 可以通過配置時鐘寄存器的CLKDIV位控制分頻因子,即SDIO_CK=SDIOCLK/(2+CLKDIV)= HCLK/(2+CLKDIV)。 配置時鐘時要注意,SD卡普遍要求SDIO_CK時鐘頻率不能超過25MHz。

W55MH32控制器的SDIO是針對MMC卡和SD卡的主設備,所以預留有8根數據線,對于SD卡最多用四根數據線。

SDIO適配器是SD卡系統主機部分,是W55MH32控制器與SD卡數據通信中間設備。SDIO適配器由五個單元組成, 分別是控制單元、命令路徑單元、數據路徑單元、寄存器單元以及FIFO,見下圖,SDIO適配器框圖:

wKgZPGgxPu2AVPCeAACigiZvycI463.png

5.1 控制單元

控制單元包含電源管理和時鐘管理功能,結構如圖 SDIO適配器控制單元 。 電源管理部件會在系統斷電和上電階段禁止SD卡總線輸出信號。時鐘管理部件控制CLK線時鐘信號生成。一般使用SDIOCLK分頻得到。

wKgZO2gxPu2AOe41AACS6F_iOdc869.png

5.2 命令路徑

命令路徑控制命令發送,并接收卡的響應,結構見下圖,SDIO適配器命令路徑:

wKgZO2gxPu6Ad9ClAAGLdAnztgU417.png

關于SDIO適配器狀態轉換流程可以參考圖 卡識別模式狀態轉換圖 , 當SD卡處于某一狀態時,SDIO適配器必然處于特定狀態與之對應。 W55MH32控制器以命令路徑狀態機(CPSM)來描述SDIO適配器的狀態變化,并加入了等待超時檢測功能, 以便退出永久等待的情況。CPSM的描述見下圖,CPSM狀態機描述圖:

wKgZPGgxPu-ADMZfAAY3pPBp3mo680.png

5.3 數據路徑

數據路徑部件負責與SD卡相互數據傳輸,內部結構見下圖,SDIO適配器數據路徑:

SD卡系統數據傳輸狀態轉換參考圖 數據傳輸模式卡狀態轉換 , SDIO適配器以數據路徑狀態機(DPSM)來描述SDIO適配器狀態變化情況。 并加入了等待超時檢測功能,以便退出永久等待情況。發送數據時,DPSM處于等待發送(Wait_S)狀態,如果數據FIFO不為空, DPSM變成發送狀態并且數據路徑部件啟動向卡發送數據。接收數據時,DPSM處于等待接收狀態,當DPSM收到起始位時變成接收狀態, 并且數據路徑部件開始從卡接收數據。DPSM狀態機描述見下圖,DPSM狀態機描述圖:

wKgZPGgxPu-AaYjZAAIajZGlYjk872.png

5.4 數據FIFO

數據FIFO(先進先出)部件是一個數據緩沖器,帶發送和接收單元。控制器的FIFO包含寬度為32bit、 深度為32字的數據緩沖器和發送/接收邏輯。其中SDIO狀態寄存器(SDIO_STA)的TXACT位用于指示當前正在發送數據, RXACT位指示當前正在接收數據,這兩個位不可能同時為1。

當TXACT為1時,可以通過AHB接口將數據寫入到傳輸FIFO。

當RXACT為1時,接收FIFO存放從數據路徑部件接收到的數據。

根據FIFO空或滿狀態會把SDIO_STA寄存器位值1,并可以產生中斷和DMA請求。

5.5 適配器寄存器

適配器寄存器包含了控制SDIO外設的各種控制寄存器及狀態寄存器,內容較多, 可以通過SDIO提供的各種結構體來了解,這些寄存器的功能都被整合到了結構體或ST標準庫之中。

6 SDIO初始化結構體

標準庫函數對SDIO外設建立了三個初始化結構體,分別為SDIO初始化結構體SDIO_InitTypeDef、SDIO命令初始化結構體SDIO_CmdInitTypeDef和SDIO數據初始化結構體SDIO_DataInitTypeDef。 這些結構體成員用于設置SDIO工作環境參數,并由SDIO相應初始化配置函數或功能函數調用,這些參數將會被寫入到SDIO相應的寄存器,達到配置SDIO工作環境的目的。

初始化結構體和初始化庫函數配合使用是標準庫精髓所在,理解了初始化結構體每個成員意義基本上就可以對該外設運用自如了。 初始化結構體定義在w55mh32_sdio.h文件中,初始化庫函數定義在w55mh32_sdio.c文件中,編程時我們可以結合這兩個文件內注釋使用。

SDIO初始化結構體用于配置SDIO基本工作環境,比如時鐘分頻、時鐘沿、數據寬度等等。它被SDIO_Init()函數使用。

代碼清單:SDIO-1 SDIO初始化結構體

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

各結構體成員的作用介紹如下:

SDIO_ClockEdge:主時鐘SDIOCLK產生CLK引腳時鐘有效沿選擇,可選上升沿或下降沿, 它設定SDIO時鐘控制寄存器(SDIO_CLKCR)的NEGEDGE位的值,一般選擇設置為高電平。

SDIO_ClockBypass:時鐘分頻旁路使用,可選使能或禁用,它設定SDIO_CLKCR寄存器的BYPASS位。如果使能旁路,SDIOCLK直接驅動CLK線輸出時鐘; 如果禁用,使用SDIO_CLKCR寄存器的CLKDIV位值分頻SDIOCLK,然后輸出到CLK線。一般選擇禁用時鐘分頻旁路。

SDIO_ClockPowerSave:節能模式選擇,可選使能或禁用,它設定SDIO_CLKCR寄存器的PWRSAV位的值。如果使能節能模式, CLK線只有在總線激活時才有時鐘輸出;如果禁用節能模式,始終使能CLK線輸出時鐘。

SDIO_BusWide:數據線寬度選擇,可選1位數據總線、4位數據總線或8為數據總線,系統默認使用1位數據總線, 操作SD卡時在數據傳輸模式下一般選擇4位數據總線。它設定SDIO_CLKCR寄存器的WIDBUS位的值。

SDIO_HardwareFlowControl:硬件流控制選擇,可選使能或禁用,它設定SDIO_CLKCR寄存器的HWFC_EN位的值。 硬件流控制功能可以避免FIFO發送上溢和下溢錯誤。

SDIO_ClockDiv:時鐘分頻系數,它設定SDIO_CLKCR寄存器的CLKDIV位的值, 設置SDIOCLK與CLK線輸出時鐘分頻系數:

CLK線時鐘頻率=SDIOCLK/([CLKDIV+2])。

7 SDIO命令初始化結構體

SDIO命令初始化結構體用于設置命令相關內容,比如命令號、命令參數、響應類型等等。它被SDIO_SendCommand()函數使用。

代碼清單:SDIO-2 SDIO命令初始化接口

typedef struct {
    uint32_t SDIO_Argument; // 命令參數
    uint32_t SDIO_CmdIndex; // 命令號
    uint32_t SDIO_Response; // 響應類型
    uint32_t SDIO_Wait;     // 等待使能
    uint32_t SDIO_CPSM;     // 命令路徑狀態機
} SDIO_CmdInitTypeDef;

各個結構體成員介紹如下:

SDIO_Argument:作為命令的一部分發送到卡的命令參數, 它設定SDIO參數寄存器(SDIO_ARG)的值。

SDIO_CmdIndex:命令號選擇, 它設定SDIO命令寄存器(SDIO_CMD)的CMDINDEX位的值。

SDIO_Response:響應類型,SDIO定義兩個響應類型:長響應和短響應。根據命令號選擇對應的響應類型。 SDIO定義了四個32位的SDIO響應寄存器(SDIO_RESPx,x=1..4),短響應只用到SDIO_RESP1。

SDIO_Wait:等待類型選擇,有三種狀態可選,一種是無等待狀態,超時檢測功能啟動;一種是等待中斷, 另外一種是等待傳輸完成。它設定SDIO_CMD寄存器的WAITPEND位和WAITINT位的值。

SDIO_CPSM:命令路徑狀態機控制,可選使能或禁用CPSM。 它設定SDIO_CMD寄存器的CPSMEN位的值。

8 SDIO數據初始化結構體

SDIO數據初始化結構體用于配置數據發送和接收參數,比如傳輸超時、數據長度、傳輸模式等等。它被SDIO_DataConfig()函數使用。

代碼清單:SDIO-3 SDIO數據初始化結構體

typedef struct {
    uint32_t SDIO_DataTimeOut;    // 數據傳輸超時
    uint32_t SDIO_DataLength;     // 數據長度
    uint32_t SDIO_DataBlockSize;  // 數據塊大小
    uint32_t SDIO_TransferDir;    // 數據傳輸方向
    uint32_t SDIO_TransferMode;   // 數據傳輸模式
    uint32_t SDIO_DPSM;           // 數據路徑狀態機
} SDIO_DataInitTypeDef;

各結構體成員介紹如下:

SDIO_DataTimeOut:設置數據傳輸以卡總線時鐘周期表示的超時周期,它設定SDIO數據定時器寄存器(SDIO_DTIMER)的值。 在DPSM進入Wait_R或繁忙狀態后開始遞減,直到0還處于以上兩種狀態則將超時狀態標志置1.

SDIO_DataLength:設置傳輸數據長度, 它設定SDIO數據長度寄存器(SDIO_DLEN)的值。

SDIO_DataBlockSize:設置數據塊大小,有多種尺寸可選, 不同命令要求的數據塊可能不同。它設定SDIO數據控制寄存器(SDIO_DCTRL)寄存器的DBLOCKSIZE位的值。

SDIO_TransferDir:數據傳輸方向,可選從主機到卡的寫操作, 或從卡到主機的讀操作。它設定SDIO_DCTRL寄存器的DTDIR位的值。

SDIO_TransferMode:數據傳輸模式,可選數據塊或數據流模式。 對于SD卡操作使用數據塊類型。它設定SDIO_DCTRL寄存器的DTMODE位的值。

SDIO_DPSM:數據路徑狀態機控制,可選使能或禁用DPSM。 它設定SDIO_DCTRL寄存器的DTEN位的值。要實現數據傳輸都必須使能SDIO_DPSM。

9 SD卡讀寫測試

9.1 代碼解析

基于 W55MH32 的 SD 卡文件系統測試程序,借助 FATFS 文件系統庫對 SD 卡進行讀寫、目錄創建與刪除等操作。下面是對代碼的詳細解釋:

1. 頭文件包含

#include "w55mh32.h"
#include 
#include "bsp_sdio_sdcard.h"
#include "sdio_test.h"
#include "delay.h"
#include "ff.h"

這些頭文件涵蓋了硬件相關的定義、標準輸入輸出庫、SD 卡驅動、延時函數以及 FATFS 文件系統庫。

2. 函數聲明

void    USART_Config(uint32_t bound);
uint8_t GetCmd(void);
void    TestList(void);
void    ShowCardInfo(void);
void    SDInfoShow(void);
void    FatfsTest(void);
void    FatfsBigDataTest(void);
void    WriteFileTest(void);
void    CreateDir(void);
void    DeleteDirFile(void);
void    ViewRootDir(void);

這里聲明了一系列函數,用于串口配置、命令獲取、測試列表顯示、SD 卡信息顯示、文件系統測試等。

3. 全局變量定義

FATFS   fs;
FIL     fnew;
FRESULT res_sd;
UINT    fnum;
BYTE    ReadBuffer[1024] = {0};
BYTE    WriteBuffer[]    = "WIZnet, create a new file system test filen";
#define TEST_FILE_LEN (2 * 1024 * 1024)
#define BUF_SIZE      (4 * 1024)
uint8_t TestBuf[BUF_SIZE];

這些變量用于存儲 FATFS 文件系統對象、文件對象、文件操作結果、讀寫文件數量、讀寫緩沖區等。

4. 主函數 main()

int main(void)
{
    uint8_t           cmd = 0;
    RCC_ClocksTypeDef clocks;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);
    delay_init();
    UART_Configuration(115200);
    RCC_GetClocksFreq(&clocks);

    printf("n");
    printf("SYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhzn",
           (float)clocks.SYSCLK_Frequency / 1000000, (float)clocks.HCLK_Frequency / 1000000,
           (float)clocks.PCLK1_Frequency / 1000000, (float)clocks.PCLK2_Frequency / 1000000, (float)clocks.ADCCLK_Frequency / 1000000);

    printf("SDIO SD Card Fatfs Test.n");
    TestList();

    while (1)
    {
        cmd = GetCmd();
        switch (cmd)
        {
        case '1': {
            printf("1.--->>>FatfsTestrn");
            FatfsTest();
            TestList();
            break;
        }
        case '2': {
            printf("1.--->>>FatfsBigDataTestrn");
            FatfsBigDataTest();
            TestList();
            break;
        }
        case '3': {
            printf("2.--->>>ViewRootDirrn");
            ViewRootDir();
            TestList();
            break;
        }
        case '4': {
            printf("3.--->>>CreateDirrn");
            CreateDir();
            TestList();
            break;
        }
        case '5': {
            printf("4.--->>>DeleteDirFilern");
            DeleteDirFile();
            TestList();
            break;
        }
        }
    }
}

主函數的功能如下:

初始化 CRC 時鐘、延時函數和串口。

打印系統時鐘信息。

顯示測試列表。

進入無限循環,不斷獲取用戶輸入的命令,并依據命令調用相應的測試函數。

5. 測試列表函數 TestList()

void TestList(void)
{
    printf("/***************************SD Card Test*******************************/n");
    printf("==========================List==========================n");
    printf("1: Create a new file (FatFs read-write test file.txt) for read-write testingn");
    printf("2: Read and write large amounts of data (FatFs read and write test file .txt), perform read and write testsn");
    printf("3: Show the file test in the root directory of the SD Cardn");
    printf("4: Create directory(/Dir1,/Dir1/Die1_1,/Dir2)n");
    printf("5: Delete files and directories (/Dir1,/Dir1/Dir1_1,/Dir2, FatFs read and write test files.txt)n");
    printf("****************************************************************************/n");
}

該函數用于顯示 SD 卡測試的選項列表。

6. SD 卡信息顯示函數 SDInfoShow()

void SDInfoShow(void)
{
    printf("/***************************SD Info Show*******************************/n");
    printf("SDCardInfo.CardType : %dn", SDCardInfo.CardType);
    printf("SDCardInfo.CardCapacity : %lld Byten", (SDCardInfo.CardCapacity));
    printf("SDCardInfo.CardBlockSize : %d Byten", SDCardInfo.CardBlockSize);
}

此函數用于顯示 SD 卡的類型、容量和塊大小等信息。

7. 獲取命令函數 GetCmd()

uint8_t GetCmd(void)
{
    uint8_t tmp = 0;

    if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE))
    {
        tmp = USART_ReceiveData(USART1);
    }
    return tmp;
}

該函數用于檢查串口是否接收到數據,若接收到則返回該數據。

8. 串口配置函數 UART_Configuration()

void UART_Configuration(uint32_t bound)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    USART_InitStructure.USART_BaudRate            = bound;
    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;
    USART_InitStructure.USART_Parity              = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART_TEST, &USART_InitStructure);
    USART_Cmd(USART_TEST, ENABLE);
}

該函數用于配置串口的 GPIO 引腳和串口參數。

9. 大數據讀寫測試函數 FatfsBigDataTest()

void FatfsBigDataTest(void)
{
    uint32_t i;

    res_sd = f_mount(&fs, "0:", 1);

    printf("nFile system test --->>> write testn");
    res_sd = f_open(&fnew, "0:FatFs read and write test files.txt", FA_OPEN_ALWAYS | FA_WRITE | FA_READ);
    if (res_sd == FR_OK)
    {
        printf("Open/create FatFs to read and write the test file.txt successfully, and write data to the filern");

        for (i = 0; i < 0xFFFFF; i++)
        {
            res_sd = f_write(&fnew, WriteBuffer, sizeof(WriteBuffer), &fnum);
            if ((i % 0x8FFF) == 0)
            {
                printf("......n");
            }
        }
        if (res_sd == FR_OK)
        {
            printf("File written successfullyn");
        }
        else
        {
            printf("File write failed (%d)n", res_sd);
        }
        f_close(&fnew);
    }
    else
    {
        printf("Failed to open/create, filern");
    }
}

該函數用于進行大數據量的文件寫入測試,先掛載文件系統,然后打開文件,循環寫入數據。

10. 文件系統測試函數 FatfsTest()

void FatfsTest(void)
{
    res_sd = f_mount(&fs, "0:", 1);

    printf("n format testn");
    if (res_sd == FR_NO_FILESYSTEM)
    {
        printf("The SD card has no file system and is about to be formattedrn");

        res_sd = f_mkfs("0:", 0, 0);

        if (res_sd == FR_OK)
        {
            printf("The SD card successfully mounted the file systemrn");
            res_sd = f_mount(NULL, "0:", 1);
            res_sd = f_mount(&fs, "0:", 1);
        }
        else
        {
            printf("SD card formatting failedrn");
            while (1);
        }
    }
    else if (res_sd != FR_OK)
    {
        printf("SD card mount failed (%d), maybe SD card initialization failedrn", res_sd);
        while (1);
    }
    else
    {
        printf("The file system is mounted and can be read and written for testingrn");
    }

    SDInfoShow();
    printf("n file system test --->>> Write testn");
    res_sd = f_open(&fnew, "0:FatFs read and write test files.txt", FA_OPEN_ALWAYS | FA_WRITE | FA_READ);
    if (res_sd == FR_OK)
    {
        printf("Open/create FatFs to read and write the test file.txt successfully, and write data to the filern");

        res_sd = f_write(&fnew, WriteBuffer, sizeof(WriteBuffer), &fnum);

        if (res_sd == FR_OK)
        {
            printf("The file was written successfully, the number of bytes written:% d The data written is: n%srn", fnum, WriteBuffer);
        }
        else
        {
            printf("File write failed (%d)n", res_sd);
        }
        f_close(&fnew);
    }
    else
    {
        printf("Failed to open/create, filern");
    }

    printf("n file system test --->>> read testn");
    res_sd = f_open(&fnew, "0:FatFs read and write test files.txt", FA_OPEN_ALWAYS | FA_READ);
    if (res_sd == FR_OK)
    {
        printf("File successfully openedrn");
        res_sd = f_read(&fnew, ReadBuffer, sizeof(ReadBuffer), &fnum);
        if (res_sd == FR_OK)
        {
            printf("File read successful. Bytes read:% d The data read was: n%srn", fnum, ReadBuffer);
        }
        else
        {
            printf("File read failed (%d)n", res_sd);
        }
    }
    else
    {
        printf("File opening failedn");
    }

    f_close(&fnew);

    f_mount(NULL, "0:", 1);
}

該函數用于進行文件系統的格式化、讀寫測試,若 SD 卡沒有文件系統則進行格式化,然后進行文件的讀寫操作。

11. 創建目錄函數 CreateDir()

void CreateDir(void)
{
    res_sd = f_mount(&fs, "0:", 1);
    if (res_sd != FR_OK)
    {
        printf("Failed to mount file system (%d)rn", res_sd);
    }

    res_sd = f_mkdir("/Dir1");
    if (res_sd == FR_OK)
    {
        printf("f_mkdir Dir1 OKrn");
    }
    else if (res_sd == FR_EXIST)
    {
        printf("Dir1 Target already exists(%d)rn", res_sd);
    }
    else
    {
        printf("f_mkdir Dir1 fail(%d)rn", res_sd);
        return;
    }

    res_sd = f_mkdir("/Dir2");
    if (res_sd == FR_OK)
    {
        printf("f_mkdir Dir2 OKrn");
    }
    else if (res_sd == FR_EXIST)
    {
        printf("Dir2 Target already exists(%d)rn", res_sd);
    }
    else
    {
        printf("f_mkdir Dir2 fail (%d)rn", res_sd);
        return;
    }

    res_sd = f_mkdir("/Dir1/Dir1_1");
    if (res_sd == FR_OK)
    {
        printf("f_mkdir Dir1_1 OKrn");
    }
    else if (res_sd == FR_EXIST)
    {
        printf("Dir1_1 Target already exists(%d)rn", res_sd);
    }
    else
    {
        printf("f_mkdir Dir1_1 fail (%d)rn", res_sd);
        return;
    }

    f_mount(NULL, "0:", 1);
}

該函數用于在 SD 卡上創建目錄 /Dir1、/Dir2 和 /Dir1/Dir1_1。

12. 刪除目錄和文件函數 DeleteDirFile()

void DeleteDirFile(void)
{
    res_sd = f_mount(&fs, "0:", 1);
    if (res_sd != FR_OK)
    {
        printf("Failed to mount file system (%d)rn", res_sd);
    }

    res_sd = f_unlink("/Dir1/Dir1_1");
    if (res_sd == FR_OK)
    {
        printf("Delete subdirectory /Dir1/Dir1_1 successrn");
    }
    else if ((res_sd == FR_NO_FILE) || (res_sd == FR_NO_PATH))
    {
        printf("No file or directory found: %srn", "/Dir1/Dir1_1");
    }
    else
    {
        printf("Deleting subdirectory/Dir1/Dir1_1 failed (errcode =% d) File read-only or directory not emptyrn", res_sd);
    }

    res_sd = f_unlink("/Dir1");
    if (res_sd == FR_OK)
    {
        printf("Delete directory/Dir1 successfullyrn");
    }
    else if ((res_sd == FR_NO_FILE) || (res_sd == FR_NO_PATH))
    {
        printf("No file or directory found : %srn", "/Dir1");
    }
    else
    {
        printf("Deleting subdirectory/Dir1/Dir1_1 failed (errcode =% d) File read-only or directory not emptyrn", res_sd);
    }

    res_sd = f_unlink("/Dir2");
    if (res_sd == FR_OK)
    {
        printf("Delete/Dir2 successfullyrn");
    }
    else if ((res_sd == FR_NO_FILE) || (res_sd == FR_NO_PATH))
    {
        printf("No file or directory found : %srn", "/Dir2");
    }
    else
    {
        printf("Deleting subdirectory/Dir1/Dir1_1 failed (errcode = %d) File read-only or directory is not emptyrn", res_sd);
    }

    res_sd = f_unlink("FatFs read and write test files.txt");
    if (res_sd == FR_OK)
    {
        printf("Delete FatFs read and write test file.txt successfullyrn");
    }
    else if ((res_sd == FR_NO_FILE) || (res_sd == FR_NO_PATH))
    {
        printf("No file or directory found : %srn", "/FatFs read and write test files.txt");
    }
    else
    {
        printf("Failed to delete FatFs read and write test file.txt(errcode = %d) File read-only or directory is not emptyrn", res_sd);
    }

    f_mount(NULL, "0:", 1);
}

該函數用于刪除之前創建的目錄和文件。

13. 查看根目錄函數 ViewRootDir()

void ViewRootDir(void)
{
    DIR      dirinf;
    FILINFO  fileinf;
    uint32_t cnt = 0;
    char     name[256];

    res_sd = f_mount(&fs, "0:", 1);
    if (res_sd != FR_OK)
    {
        printf("Failed to mount file system (%d)rn", res_sd);
    }

    res_sd = f_opendir(&dirinf, "/");
    if (res_sd != FR_OK)
    {
        printf("Failed to open root directory (%d)rn", res_sd);
        return;
    }

    fileinf.lfname = name;
    fileinf.lfsize = 256;

    printf("attribute		|	file size	|	short filename	|	long file namern");
    for (cnt = 0;; cnt++)
    {
        res_sd = f_readdir(&dirinf, &fileinf);
        if (res_sd != FR_OK || fileinf.fname[0] == 0)
        {
            break;
        }

        if (fileinf.fname[0] == '.')
        {
            continue;
        }

        if (fileinf.fattrib & AM_DIR)
        {
            printf("(0x%02d)directory", fileinf.fattrib);
        }
        else
        {
            printf("(0x%02d)attribute", fileinf.fattrib);
        }

        printf("%10d	", fileinf.fsize);
        printf("	%s |", fileinf.fname);
        printf("	%srn", (char *)fileinf.lfname);
    }

    f_mount(NULL, "0:", 1);
}

14. 串口發送字符函數 SER_PutChar() 和 fputc()

int SER_PutChar(int ch)
{
    while (!USART_GetFlagStatus(USART_TEST, USART_FLAG_TC));
    USART_SendData(USART_TEST, (uint8_t)ch);

    return ch;
}

int fputc(int c, FILE *f)
{
    if (c == 'n')
    {
        SER_PutChar('r');
    }
    return (SER_PutChar(c));
}

這段代碼借助 FATFS 文件系統庫,實現了對 SD 卡的文件讀寫、目錄創建與刪除、查看根目錄等操作,并且提供了一個簡單的菜單界面,方便用戶進行測試。

9.2 下載驗證

1. 程序上電運行

wKgZPGgxPu2ATy2dAACSv0YBOXc026.png

2. 輸入命令測試

通過鍵盤輸入菜單中的數字鍵(1~5)執行對應功能:

(1) 測試 1: 基礎文件讀寫 (輸入 1)

功能:

創建文件 FatFs read and write test files.txt,寫入文本并回讀。

wKgZO2gxPu6AH6AbAADbCd6uZCQ425.png

(2) 測試 2: 大數據量讀寫 (輸入 2)

功能:

向文件中寫入 2MB 數據(用于壓力測試),每寫入 36KB 輸出一次進度。

wKgZO2gxPu6AObv_AACplFmBSf0740.png

(3) 測試 3: 查看根目錄 (輸入 3)

功能:

顯示 SD 卡根目錄下的文件和子目錄。

wKgZO2gxPu6AObv_AACplFmBSf0740.png

(4) 測試 4: 創建目錄 (輸入 4)

功能:

創建 /Dir1, /Dir1/Dir1_1, /Dir2 目錄。

wKgZPGgxZ9eAE0iYAACd8E029SQ434.jpg

(5)測試 5: 刪除目錄/文件 (輸入 5)

功能:

刪除測試文件和目錄(需確保目錄為空)。

wKgZO2gxPu6AbBMSAACdWyCg5k8040.png

WIZnet 是一家無晶圓廠半導體公司,成立于 1998 年。產品包括互聯網處理器 iMCU?,它采用 TOE(TCP/IP 卸載引擎)技術,基于獨特的專利全硬連線 TCP/IP。iMCU? 面向各種應用中的嵌入式互聯網設備。

WIZnet 在全球擁有 70 多家分銷商,在香港、韓國、美國設有辦事處,提供技術支持和產品營銷。

香港辦事處管理的區域包括:澳大利亞、印度、土耳其、亞洲(韓國和日本除外)。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 單片機
    +關注

    關注

    6065

    文章

    44946

    瀏覽量

    648071
  • 控制器
    +關注

    關注

    114

    文章

    17026

    瀏覽量

    183298
  • SD卡
    +關注

    關注

    2

    文章

    578

    瀏覽量

    65311
  • SDIO
    +關注

    關注

    2

    文章

    75

    瀏覽量

    19807
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    第二十五章 FLASH

    本文介紹了W55MH32的FLASH模塊,由主存儲器、信息塊和接口寄存器組成。讀取需注意等待時間,編程由FPEC管理,需半字寫入,擦除分頁擦除和整片擦除,介紹了關鍵寄存器及讀寫測試例程。
    的頭像 發表于 05-29 16:03 ?700次閱讀
    <b class='flag-5'>第二十五章</b> FLASH

    《DNK210使用指南 -CanMV版 V1.0》第二十五章 LCD圖片顯示實驗

    第二十五章 LCD圖片顯示實驗 本章將介紹在LCD上的圖片顯示。通過本章的學習,讀者將學習到LCD上圖片的顯示。本章分為如下幾個小節:25.1 lcd模塊介紹25.2 硬件設計25.3 程序設計
    發表于 10-23 09:34

    【正點原子FPGA連載】第二十七章gpio子系統下的LED驅動實驗-領航者ZYNQ之linux開發指南

    的,需要注意的是,第240~256行,驅動模塊的出口函數中一定要把申請的gpio管腳給釋放,通過gpio_free函數釋放gpio。27.3.3編寫測試APP本章直接使用第二十五章測試APP,將
    發表于 09-16 17:40

    在顯示器上顯示出了靜態的彩條圖案

    關注正點原子公眾號,獲取最新資料更新第二十五章HDMI方塊移動實驗在HDMI彩條顯示實驗中,我們成功地在顯示器上顯示出了靜態的彩條圖案。本章我們通
    發表于 12-07 12:50

    第二十五講 同步計數器

    第二十五講 同步計數器 7.3.2 同步計數器一、同步二進制計數器1.同步二進制加法計數器JK觸發器組成的4位同步二進制加法
    發表于 03-30 16:28 ?9675次閱讀
    <b class='flag-5'>第二十五</b>講 同步計數器

    模擬電路網絡課件 第二十五節:集成運算放大器中的電流源

    模擬電路網絡課件 第二十五節:集成運算放大器中的電流源 6.1 集成運算放大器中的電流源 一、三極管電流源
    發表于 09-17 11:23 ?2322次閱讀
    模擬電路網絡課件 <b class='flag-5'>第二十五</b>節:集成運算放大器中的電流源

    【正點原子FPGA連載】第二十五章HDMI方塊移動實驗 -摘自【正點原子】新起點之FPGA開發指南_V2.1

    【正點原子FPGA連載】第二十五章HDMI方塊移動實驗 -摘自【正點原子】新起點之FPGA開發指南_V2.1
    發表于 11-24 14:36 ?13次下載
    【正點原子FPGA連載】<b class='flag-5'>第二十五章</b>HDMI方塊移動實驗 -摘自【正點原子】新起點之FPGA開發指南_V2.1

    2023高交會|第二十五屆中國國際高新技術交易會·招商工作全面啟動

    2023高交會|第二十五屆中國國際高新技術交易會·招商工作全面啟動
    的頭像 發表于 07-21 17:53 ?1422次閱讀
    2023高交會|<b class='flag-5'>第二十五</b>屆中國國際高新技術交易會·招商工作全面啟動

    火熱預定中2023第二十五屆中國國際高新技術交易會11.15-11.19日

    火熱預定中----2023深圳第二十五屆中國國際高新技術交易會11.15-11.19日
    的頭像 發表于 08-18 14:39 ?1055次閱讀

    火熱招商--2023第二十五屆中國國際高新技術交易會11.15-11.19日

    火熱招商中----2023第二十五屆中國國際高新技術交易會11.15-11.19盛大召開
    的頭像 發表于 08-23 09:47 ?814次閱讀

    中軟國際與深開鴻邀您相約第二十五屆中國國際軟件博覽會

    ? 原文標題:中軟國際與深開鴻邀您相約第二十五屆中國國際軟件博覽會 文章出處:【微信公眾號:中軟國際】歡迎添加關注!文章轉載請注明出處。
    的頭像 發表于 08-31 13:10 ?641次閱讀

    上海貝嶺榮獲“第二十五屆上市公司金信披獎”

    11月23日,由中國證券報、南通市人民政府聯合主辦的“2023上市公司高質量發展論壇暨第二十五屆上市公司金牛獎頒獎典禮”在江蘇南通隆重舉行,備受矚目的上市公司金牛獎榜單正式揭曉。
    的頭像 發表于 12-01 10:12 ?751次閱讀

    【GD32F303紅楓派開發板使用手冊】第二十三講 SDIO-SD讀寫實驗

    通過本實驗主要學習以下內容: ?SDIO操作原理 ?SD讀寫實現
    的頭像 發表于 06-23 10:49 ?1091次閱讀
    【GD32F303紅楓派開發板使用手冊】<b class='flag-5'>第二十</b>三講 <b class='flag-5'>SDIO-SD</b><b class='flag-5'>卡</b><b class='flag-5'>讀寫</b>實驗

    中國中車多家子公司榮獲第二十五屆中國專利獎

    近日,國家知識產權局發布了關于第二十五屆中國專利獎授獎的決定,中國中車多家子公司獲獎。
    的頭像 發表于 06-13 11:47 ?271次閱讀

    國星光電榮獲第二十五屆中國專利優秀獎

    近日,國家知識產權局發布《關于第二十五屆中國專利獎授獎的決定》,國星光電憑借發明專利“一種量子點發光器件及其制造方法” 榮獲中國專利優秀獎。
    的頭像 發表于 06-13 16:04 ?206次閱讀
    主站蜘蛛池模板: 网红和老师啪啪对白清晰 | 亚洲一区二区三区免费在线观看 | 性欧美大战久久久久久久野外 | 精品videosex性欧美 | 中文字幕在线播放第一页 | 黄色日批网站 | 一级欧美视频 | 粗又长好猛好爽 | 国产亚洲精品成人一区看片 | 深夜视频在线播放视频在线观看免费观看 | 被啪漫画羞羞漫画 | 亚洲第一永久在线观看 | 黄篇网站在线观看 | 永久黄色免费网站 | 日韩有码电影 | 欧美大色网 | 717影院理论午夜伦八戒 | 亚洲一区二区三区深夜天堂 | 日日噜噜噜夜夜爽爽狠狠 | 男人j进人女人j 的视频 | 国产色司机在线视频免费观看 | 亚洲天堂成人网 | 人人干人人艹 | 亚洲精品日韩专区silk | 在线观看视频你懂的 | 欧美一级特黄啪啪片免费看 | 色啦啦影院 | 热99在线视频 | 国产一区中文字幕 | 五月天激情丁香 | free性欧美video | 国产黄mmd在线观看免费 | 国产亚洲第一伦理第一区 | 亚洲欧美日韩高清mmm777 | 欧美一区二区三区大片 | 午夜影院在线观看视频 | 四虎电影免费观看网站 | 12306影院午夜入口 | 日本免费人成黄页在线观看视频 | 国产精品三区四区 | 男人不识本网站上遍色站也枉然 |