0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

SD卡基礎(chǔ)讀寫實(shí)驗(yàn)

汽車電子技術(shù) ? 來(lái)源:滑小稽筆記 ? 作者:電子技術(shù)園地 ? 2023-03-01 14:46 ? 次閱讀

20.1 概述

SD卡是嵌入式系統(tǒng)中最常見(jiàn)的存儲(chǔ)器,不僅容量可以做的很大,并且接口通用,支持SPI/SDIO驅(qū)動(dòng),尺寸可供選擇,能滿足不同應(yīng)用的要求。STM32F1系列自帶了標(biāo)準(zhǔn)的4位SDIO接口,最高通信速度可達(dá)24MHz,最高每秒能傳輸12M字節(jié)的數(shù)據(jù)。

20.1.1 SDIO框圖

STM32F1的SDIO控制器包括2部分,SDIO適配器模塊和AHB總線接口,功能框圖如下圖所示。

圖片

其中SDIO適配器模塊主要用于實(shí)現(xiàn)所有MMC/SD卡的相關(guān)功能,如時(shí)鐘的產(chǎn)生,命令和數(shù)據(jù)的傳輸,AHB總線接口則用于操作SDIO適配器模塊中的寄存器并產(chǎn)生中斷和DMA請(qǐng)求信號(hào)。復(fù)位后默認(rèn)情況下SDIO_D0用于數(shù)據(jù)傳輸。初始化后主機(jī)可以改變數(shù)據(jù)總線的寬度。

如果一個(gè)多媒體卡接到了總線上,則SDIO_D0、SDIO_D[3:0]或SDIO_D[7:0]可以用于數(shù)據(jù)傳輸。MMC版本V3.31和之前版本的協(xié)議只支持1位數(shù)據(jù)線,所以只能用SDIO_D0(為了通用性考慮,在程序里面我們只要檢測(cè)到是MMC卡就設(shè)置為1位總線數(shù)據(jù))。

如果一個(gè)SD卡接到了總線上,可以通過(guò)主機(jī)配置數(shù)據(jù)傳輸使用SDIO_D0或SDIO_D[3:0]。所有的數(shù)據(jù)線都工作在推挽模式。

SDIO_CMD有兩種操作模式:

(1)用于初始化時(shí)的開(kāi)路模式(僅用于MMC版本V3.31或之前版本)

(2)用于命令傳輸?shù)耐仆炷J剑⊿D卡和MMCV4.2在初始化時(shí)也使用推挽驅(qū)動(dòng))

20.1.2 SDIO時(shí)鐘

從SDIO框圖我們可以看到SDIO總共有3個(gè)時(shí)鐘,分別是:

(1)卡時(shí)鐘SDIO_CK:每個(gè)時(shí)鐘周期在命令和數(shù)據(jù)線上傳輸1位命令或數(shù)據(jù)。對(duì)于多媒體卡V3.31協(xié)議,時(shí)鐘頻率可以在0MHz至20MHz間變化;對(duì)于多媒體卡V4.0/4.2協(xié)議,時(shí)鐘頻率可以在0MHz至48MHz間變化;對(duì)于SD卡,時(shí)鐘頻率可以在0MHz至25MHz間變化。

(2)SDIO適配器時(shí)鐘SDIOCLK:該時(shí)鐘用于驅(qū)動(dòng)SDIO適配器,其頻率等于AHB總線頻率HCLK,并用于產(chǎn)生SDIO_CK時(shí)鐘

(3)AHB總線接口時(shí)鐘HCLK/2:該時(shí)鐘用于驅(qū)動(dòng)SDIO的AHB總線接口,其頻率為HCLK/2。

我們的SD卡時(shí)鐘SDIO_CK,根據(jù)卡的不同,可能有好幾個(gè)區(qū)間,這就涉及到時(shí)鐘頻率的設(shè)置,SDIO_CK與SDIOCLK的關(guān)系為:

SDIO_CK=SDIOCLK/(2+CLKDIV)

其中,SDIOCLK為HCLK,一般是72MHz,而CLKDIV則是分配系數(shù),可以通過(guò)SDIO的SDIO_CLKCR寄存器進(jìn)行設(shè)置,確保SDIO_CK不超過(guò)卡的最大操作頻率。

注:在SD卡剛剛初始化的時(shí)候,其時(shí)鐘頻率SDIO_CK不能超過(guò)400KHz,否則可能無(wú)法完成初始化。在初始化以后,就可以設(shè)置時(shí)鐘頻率到最大了,但不可超過(guò)SD卡的最大操作時(shí)鐘頻率。

20.1.3 SDIO的命令與響應(yīng)

SDIO的命令分為應(yīng)用相關(guān)命令ACMD和通用命令CMD兩部分,應(yīng)用相關(guān)命令A(yù)CMD的發(fā)送,必須先發(fā)送通用命令CMD55,然后才能發(fā)送應(yīng)用相關(guān)命令A(yù)CMD。SDIO的所有命令和響應(yīng)都是通過(guò)SDIO_CMD引腳傳輸?shù)?,任何命令的長(zhǎng)度都是固定為48位,SDIO的命令格式如下表所示。

Bit位 寬度 說(shuō)明
47 1 0 起始位
46 1 1 傳輸位
45:40 6 - 命令索引
39:8 32 - 參數(shù)
7:1 7 - CRC7
0 1 1 結(jié)束位

所有的命令都是由STM32F1發(fā)出,其中開(kāi)始位、傳輸位、CRC7和結(jié)束位由SDIO硬件控制,我們需要設(shè)置的就只有命令索引和參數(shù)部分。其中命令索引在SDIO_CMD寄存器里面設(shè)置,命令參數(shù)則由寄存器SDIO_ARG設(shè)置。一般情況下,選中的SD卡在接收到命令之后,都會(huì)回復(fù)一個(gè)應(yīng)答(但是CMD0無(wú)應(yīng)答),這個(gè)應(yīng)答我們稱之為響應(yīng),響應(yīng)也是在CMD線上串行傳輸?shù)?。STM32F1的SDIO控制器支持2種響應(yīng)類型,48位的短響應(yīng)和136位的長(zhǎng)響應(yīng),這兩種響應(yīng)類型都帶CRC錯(cuò)誤檢測(cè),不帶CRC的響應(yīng)應(yīng)該忽略CRC錯(cuò)誤標(biāo)志,如CMD1的響應(yīng)。

短響應(yīng)的格式如下表所示。

Bit位 寬度 說(shuō)明
47 1 0 起始位
46 1 0 傳輸位
45:40 6 - 命令索引
39:8 32 - 參數(shù)
7:1 7 - CRC7或者1111111
0 1 1 結(jié)束位

長(zhǎng)響應(yīng)的格式如下表所示。

Bit位 寬度 說(shuō)明
135 1 0 起始位
134 1 0 傳輸位
133:128 6 111111 保留
127:1 127 - CID或CSD(包括內(nèi)部CRC7)
0 1 1 結(jié)束位

硬件為我們?yōu)V除了開(kāi)始位、傳輸位、CRC7以及結(jié)束位等信息,對(duì)于短響應(yīng),命令索引存放在SDIO_RESPCMD寄存器,參數(shù)則存放在SDIO_RESP1寄存器里面。對(duì)于長(zhǎng)響應(yīng),則僅留CID/CSD位域,存放在SDIO_RESP1到SDIO_RESP4等4個(gè)寄存器。SD卡總共有5類響應(yīng)(R1、R2、R3、R6、R7),這里以R1為例簡(jiǎn)單介紹一下。R1(普通響應(yīng)命令)響應(yīng)屬于短響應(yīng),其長(zhǎng)度為48位,R1響應(yīng)的格式如下表所示。

Bit位 寬度 說(shuō)明
47 1 0 起始位
46 1 1 傳輸位
45:40 6 X 命令索引
39:8 32 X 參數(shù)
7:1 7 X CRC7
0 1 1 結(jié)束位

在收到R1響應(yīng)后,我們可以從SDIO_RESPCMD寄存器和SDIO_RESP1寄存器分別讀出命令索引和卡狀態(tài)信息。

20.1.4 數(shù)據(jù)塊讀操作

對(duì)于SD卡,數(shù)據(jù)是以數(shù)據(jù)塊的形式傳輸?shù)模覀兂S玫目ň褪荢D卡,所以不考慮MMC形式的讀寫操作,因?yàn)镸MC卡數(shù)據(jù)以數(shù)據(jù)塊或者數(shù)據(jù)流的形式傳輸。

從機(jī)在收到主機(jī)相關(guān)命令后,開(kāi)始發(fā)送數(shù)據(jù)塊給主機(jī),所有數(shù)據(jù)塊都帶有CRC校驗(yàn)值,CRC由SDIO硬件自動(dòng)處理,單個(gè)數(shù)據(jù)塊讀的時(shí)候,在收到1個(gè)數(shù)據(jù)塊以后即可以停止了,不需要發(fā)送停止命令CMD12。但是多塊數(shù)據(jù)讀的時(shí)候,SD卡將一直發(fā)送數(shù)據(jù)給主機(jī),直到接到主機(jī)發(fā)送的STOP命令CMD12。

SDIO多數(shù)據(jù)塊的讀操作如下圖所示。

圖片

20.1.5 數(shù)據(jù)塊寫操作

數(shù)據(jù)塊寫操作同數(shù)據(jù)塊讀操作基本類似,只是數(shù)據(jù)塊寫的時(shí)候,多了一個(gè)忙判斷,新的數(shù)據(jù)塊必須在SD卡非忙的時(shí)候發(fā)送。這里的忙信號(hào)由SD卡拉低SDIO_D0,以表示忙,SDIO硬件自動(dòng)控制,不需要我們軟件處理。

圖片

20.2 SDIO相關(guān)寄存器

20.2.1 SDIO電源控制寄存器:SDIO_POWER

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- CTRL

Bit 1~Bit 0:電源控制位

00:電源關(guān)閉,卡的時(shí)鐘停止

01:保留

10:保留的上電狀態(tài)

11:上電狀態(tài),卡的時(shí)鐘開(kāi)啟

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

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
-
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- HWFC_EN NEGEDGE WIDBUS BYPASS PWRSAV CLKEN CLKDIV

Bit 14:硬件流控制使能

0:關(guān)閉硬件流控制

1:使能硬件流控制

Bit 13:SDIO_CK相位選擇位

0:在主時(shí)鐘SDIOCLK的上升沿產(chǎn)生SDIO_CK

1:在主時(shí)鐘SDIOCLK的下降沿產(chǎn)生SDIO_CK

Bit 12~Bit 11:寬總線模式使能位

00:默認(rèn)總線模式,使用SDIO_D0

01:4位總線模式,使用SDIO_D[3:0]

10:8位總線模式,使用SDIO_D[7:0]

Bit 10:旁路時(shí)鐘分頻器

0:關(guān)閉旁路:驅(qū)動(dòng)SDIO_CK輸出信號(hào)之前,依據(jù)CLKDIV數(shù)值對(duì)SDIOCLK分頻

1:使能旁路:SDIOCLK直接驅(qū)動(dòng)SDIO_CK輸出信號(hào)

Bit 9:省電配置位(為了省電,當(dāng)總線為空閑時(shí),設(shè)置PWRSAV位可以關(guān)閉SDIO_CK時(shí)鐘輸出)

0:始終輸出SDIO_CK

1:僅在有總線活動(dòng)時(shí)才輸出SDIO_CK

Bit 8:時(shí)鐘使能位

0:SDIO_CK關(guān)閉

1:SDIO_CK使能

Bit 7~Bit 0:時(shí)鐘分頻系數(shù)

這個(gè)域定義了輸入時(shí)鐘(SDIOCLK)與輸出時(shí)鐘(SDIO_CK)間的分頻系數(shù):SDIO_CK頻率=SDIOCLK/[CLKDIV+2]

20.2.3 SDIO參數(shù)寄存器:SDIO_ARG

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
CMDARG[31:16]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
CMDARG[16:0]

Bit 31~Bit 0:命令參數(shù)

屬于發(fā)送到卡中命令的一部分,如果一個(gè)命令包含一個(gè)參數(shù),必須在寫命令到命令寄存器之前加載這個(gè)寄存器

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

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
-
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- RESPCMD

Bit 5~Bit 0:響應(yīng)的命令索引

只讀位,包含最后收到的命令響應(yīng)中的命令索引

20.2.5 SDIO相應(yīng)寄存器組:SDIO_RESP1~SDIO_RESP4

寄存器 短響應(yīng) 長(zhǎng)響應(yīng)
SDIO_RESP1 卡狀態(tài)[31:0] 卡狀態(tài)[127:96]
SDIO_RESP2 未使用 卡狀態(tài)[95:64]
SDIO_RESP3 未使用 卡狀態(tài)[31:0]
SDIO_RESP4 未使用 卡狀態(tài)[31:0]

注:總是先收到卡狀態(tài)的最高位,SDIO_RESP3寄存器的最低位始終為0。

20.2.6 SDIO命令寄存器:SDIO_CMD

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
-
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- CE_ATACMD nIEN ENCMDcomp1 SDIOSuspend CPSMEN WAITPEND WAITINT WAITRESP CMDINDEX

Bit 14:CE-ATA命令

如果設(shè)置該位,CPSM轉(zhuǎn)至CMD61

Bit 13:不使能中斷

如果未設(shè)置該位,則使能CE-ATA設(shè)備的中斷

Bit 12:使能CMD完成

如果設(shè)置該位,則使能命令完成信號(hào)

Bit 11:SDIO暫停命令

如果設(shè)置該位,則將要發(fā)送的命令是一個(gè)暫停命令(只能用于SDIO卡)

Bit 10:命令通道狀態(tài)機(jī)使能位

如果設(shè)置該位,則使能CPSM

Bit 9:CPSM等待數(shù)據(jù)傳輸結(jié)束(CmdPend內(nèi)部信號(hào))

如果設(shè)置該位,則CPSM在開(kāi)始發(fā)送一個(gè)命令之前等待數(shù)據(jù)傳輸結(jié)束

Bit 8:CPSM等待中斷請(qǐng)求

如果設(shè)置該位,則CPSM關(guān)閉命令超時(shí)控制并等待中斷請(qǐng)求

Bit 7~Bit 6:等待響應(yīng)位

00:無(wú)響應(yīng),期待CMDSENT標(biāo)志

01:短響應(yīng),期待CMDREND或CCRCFAIL標(biāo)志

10:無(wú)響應(yīng),期待CMDSENT標(biāo)志

11:長(zhǎng)響應(yīng),期待CMDREND或CCRCFAIL標(biāo)志

Bit 5~Bit 0:命令索引,作為命令的一部分發(fā)送到卡中

20.2.7 SDIO數(shù)據(jù)定時(shí)器:SDIO_DTIMER

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
DATATIME[31:16]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
DATATIME[15:0]

Bit 31~Bit 0:數(shù)據(jù)超時(shí)時(shí)間,以卡總線時(shí)鐘周期為單位的數(shù)據(jù)超時(shí)時(shí)間

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

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
- DATALENGTH[24:16]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
DATALENGTH[15:0]

Bit 24~Bit 0:數(shù)據(jù)長(zhǎng)度,要傳輸?shù)臄?shù)據(jù)字節(jié)數(shù)目

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

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
-
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
- SDIOEN RWMOD RWSTOP RWSTART DBLOCKSIZE DMAEN DTMODE DTDIR DTEN

Bit 11:SDIO使能功能

如果設(shè)置了該位,則DPSM執(zhí)行SDIO卡特定的操作

Bit 10:讀等待模式

0:停止SDIO_CK控制讀等待

1:使用SDIO_D2控制讀等待

Bit 9:讀等待停止

0:如果設(shè)置了RWSTART,執(zhí)行讀等待

1:如果設(shè)置了RWSTART,停止讀等待

Bit 8:讀等待開(kāi)始

設(shè)置該位開(kāi)始讀等待操作

Bit 7~Bit 4:數(shù)據(jù)塊長(zhǎng)度,當(dāng)選擇了塊數(shù)據(jù)傳輸模式,該域定義數(shù)據(jù)塊長(zhǎng)度

0000:塊長(zhǎng)度=1字節(jié)

0001:塊長(zhǎng)度=2字節(jié)

0010:塊長(zhǎng)度=4字節(jié)

0011:塊長(zhǎng)度=8字節(jié)

0100:塊長(zhǎng)度=16字節(jié)

0101:塊長(zhǎng)度=32字節(jié)

0110:塊長(zhǎng)度=64字節(jié)

0111:塊長(zhǎng)度=128字節(jié)

1000:塊長(zhǎng)度=256字節(jié)

1001:塊長(zhǎng)度=512字節(jié)

1010:塊長(zhǎng)度=1024字節(jié)

1011:塊長(zhǎng)度=2048字節(jié)

1100:塊長(zhǎng)度=4096字節(jié)

1101:塊長(zhǎng)度=8192字節(jié)

1110:塊長(zhǎng)度=16384字節(jié)

1111:保留

Bit 3:DMA使能位

0:關(guān)閉DMA

   1:使能DMA

Bit 2:數(shù)據(jù)傳輸模式

0:塊數(shù)據(jù)傳輸

   1:流數(shù)據(jù)傳輸

Bit 1:數(shù)據(jù)傳輸方向

0:控制器至卡

   1:卡至控制器

Bit 0:數(shù)據(jù)傳輸使能位

如果設(shè)置該位為1,則開(kāi)始數(shù)據(jù)傳輸。根據(jù)DTSIR方向位,DPSM進(jìn)入Wait_S或Wait_R狀態(tài),如果在傳輸?shù)囊婚_(kāi)始就設(shè)置了RWSTART位,則DPSM進(jìn)入讀等待狀態(tài)。不需要在數(shù)據(jù)傳輸結(jié)束后清除使能位,但必須更改SDIO_DCTRL以允許新的數(shù)據(jù)傳輸。

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

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
- CEATAEND SDIOIT RXDAVL TXDAVL RXFIFOE TXFIFOE RXFIFOF TXFIFOF
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
RXFIFOHF TXFIFOHF RXACT TXACT CMDACT DBCKEND STBITERR DATAEND CMDSENT CMDREND RXOVERR TXUNDERR DTMEOUT CTIMEOUT DCRCFAIL CCRCFAIL

Bit 23:在CMD61接收到CE-ATA命令完成信號(hào)

Bit 22:收到SDIO中斷

Bit 21:在接收FIFO中的數(shù)據(jù)可用

Bit 20:在發(fā)送FIFO中的數(shù)據(jù)可用

Bit 19:接收FIFO空

Bit 18:發(fā)送FIFO空

若使用了硬件流控制,當(dāng)FIFO包含2個(gè)字時(shí),TXFIFOE信號(hào)變?yōu)橛行А?

Bit 17:接收FIFO滿

若使用了硬件流控制,當(dāng)FIFO還差2個(gè)字滿時(shí),RXFIFOF信號(hào)變?yōu)橛行А?

Bit 16:發(fā)送FIFO滿

Bit 15:接收FIFO半滿,F(xiàn)IFO中至少還有8個(gè)字

Bit 14:發(fā)送FIFO半空,F(xiàn)IFO中至少還可以寫入8個(gè)字。

Bit 13:正在接收數(shù)據(jù)

Bit 12:正在發(fā)送數(shù)據(jù)

Bit 11:正在傳輸命令

Bit 10:已發(fā)送/接收數(shù)據(jù)塊(CRC檢測(cè)成功)

Bit 9:在寬總線模式,沒(méi)有在所有數(shù)據(jù)信號(hào)上檢測(cè)到起始位

Bit 8:數(shù)據(jù)結(jié)束(數(shù)據(jù)計(jì)數(shù)器,SDIO_DCOUNT=0)

Bit 7:命令已發(fā)送(不需要響應(yīng))

Bit 6:已接收到響應(yīng)(CRC檢測(cè)成功)

Bit 5:接收FIFO上溢錯(cuò)誤

Bit 4:發(fā)送FIFO下溢錯(cuò)誤

Bit 3:數(shù)據(jù)超時(shí)

Bit 2:命令響應(yīng)超時(shí)

命令超時(shí)時(shí)間是一個(gè)固定的值,為64個(gè)SDIO_CK時(shí)鐘周期。

Bit 1:已發(fā)送/接收數(shù)據(jù)塊(CRC檢測(cè)失?。?/p>

Bit 0:已收到命令響應(yīng)(CRC檢測(cè)失敗)

注:狀態(tài)寄存器可以用來(lái)查詢SDIO控制器的當(dāng)前狀態(tài)。比如SDIO_STA的位2表示命令響應(yīng)超時(shí),說(shuō)明SDIO的命令響應(yīng)出了問(wèn)題。我們通過(guò)設(shè)置SDIO_ICR的位2則可以清除這個(gè)超時(shí)標(biāo)志,而設(shè)置SDIO_MASK的位2,則可以開(kāi)啟命令響應(yīng)超時(shí)中斷,設(shè)置為0關(guān)閉。

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

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
FIFODATA[31:16]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
FIFODATA[15:0]

Bit 31~Bit 0:接收或發(fā)送FIFO數(shù)據(jù)

FIFO數(shù)據(jù)占據(jù)32個(gè)32位的字,地址為:SDIO基址+0x80至SDIO基址+0xFC

數(shù)據(jù)FIFO寄存器包括接收和發(fā)送FIFO,他們由一組連續(xù)的32個(gè)地址上的32個(gè)寄存器組成,CPU可以使用FIFO讀寫多個(gè)操作數(shù)。例如我們要從SD卡讀數(shù)據(jù),就必須讀SDIO_FIFO寄存器,要寫數(shù)據(jù)到SD卡,則要寫SDIO_FIFO寄存器。SDIO將這32個(gè)地址分為16個(gè)一組,發(fā)送接收各占一半。而我們每次讀寫的時(shí)候,最多就是讀取發(fā)送FIFO或?qū)懭虢邮誇IFO的一半大小的數(shù)據(jù),也就是8個(gè)字(32個(gè)字節(jié)),在操作SDIO_FIFO(不論讀出還是寫入)必須是以4字節(jié)對(duì)齊的內(nèi)存進(jìn)行操作,否則將導(dǎo)致出錯(cuò)。

20.3 SD卡初始化

20.3.1 卡上電流

圖片

20.3.2 卡初始化流程

圖片

20.4 實(shí)驗(yàn)例程

功能:利用STM32F1的SDIO模塊讀取SD的容量并通過(guò)TFTLCD顯示。

(1)創(chuàng)建sdio_sdcard.h文件,并輸入以下代碼。

#ifndef _SDIO_SDCARD_H_
#define _SDIO_SDCARD_H_
#include "sys.h"
/*********************************************************************************************************
                SD    卡    數(shù)    據(jù)    定    義
*********************************************************************************************************/
//用戶配置區(qū)
#define SDIO_INIT_CLK_DIV        0x76                                  //SDIO初始化頻率,最大400Kh
#define SDIO_TRANSFER_CLK_DIV    0x00                                  //SDIO傳輸頻率,該值太小可能會(huì)導(dǎo)致讀寫文件出錯(cuò)
//SDIO工作模式定義,通過(guò)SD_SetDeviceMode函數(shù)設(shè)置
#define SD_POLLING_MODE      0                                      //查詢模式,該模式下,如果讀寫有問(wèn)題,建議增大SDIO_TRANSFER_CLK_DIV的設(shè)置
#define SD_DMA_MODE        1                                      //DMA模式,該模式下,如果讀寫有問(wèn)題,建議增大SDIO_TRANSFER_CLK_DIV的設(shè)置
//SDIO 各種錯(cuò)誤枚舉定義
typedef enum
{   
  //特殊錯(cuò)誤定義 
  SD_CMD_CRC_FAIL                    = 1,                                //收到命令響應(yīng)(CRC校驗(yàn)失敗)
  SD_DATA_CRC_FAIL                   = 2,                                //發(fā)送/接收數(shù)據(jù)塊(CRC校驗(yàn)失?。?/span>
  SD_CMD_RSP_TIMEOUT                 = 3,                                //命令響應(yīng)超時(shí)
  SD_DATA_TIMEOUT                    = 4,                                //數(shù)據(jù)超時(shí)
  SD_TX_UNDERRUN                     = 5,                                //傳輸FIFO運(yùn)行
  SD_RX_OVERRUN                      = 6,                                //接收FIFO運(yùn)行
  SD_START_BIT_ERR                   = 7,                                //在寬總線模式下的所有數(shù)據(jù)信號(hào)上未檢測(cè)到起始位
  SD_CMD_OUT_OF_RANGE                = 8,                                //CMD的參數(shù)超出范圍
  SD_ADDR_MISALIGNED                 = 9,                                //地址沒(méi)有對(duì)齊
  SD_BLOCK_LEN_ERR                   = 10,                              //卡不允許傳輸?shù)膲K長(zhǎng)度,或者傳輸?shù)淖止?jié)數(shù)與塊長(zhǎng)度不匹配
  SD_ERASE_SEQ_ERR                   = 11,                              //擦除命令序列中發(fā)生錯(cuò)誤
  SD_BAD_ERASE_PARAM                 = 12,                              //刪除組的無(wú)效選擇
  SD_WRITE_PROT_VIOLATION            = 13,                              //試圖對(duì)寫保護(hù)塊進(jìn)行編程
  SD_LOCK_UNLOCK_FAILED              = 14,                              //在unlock命令中檢測(cè)到序列或密碼錯(cuò)誤,或者試圖訪問(wèn)鎖定的卡
  SD_COM_CRC_FAILED                  = 15,                              //前一個(gè)命令的CRC校驗(yàn)失敗
  SD_ILLEGAL_CMD                     = 16,                              //命令對(duì)卡狀態(tài)無(wú)效
  SD_CARD_ECC_FAILED                 = 17,                              //已應(yīng)用卡內(nèi)部ECC,但未能更正數(shù)據(jù)
  SD_CC_ERROR                        = 18,                              //內(nèi)部卡控制錯(cuò)誤
  SD_GENERAL_UNKNOWN_ERROR           = 19,                              //通用或未知錯(cuò)誤
  SD_STREAM_READ_UNDERRUN            = 20,                              //卡無(wú)法在流讀取操作中維持?jǐn)?shù)據(jù)傳輸
  SD_STREAM_WRITE_OVERRUN            = 21,                              //卡無(wú)法維持流模式下的數(shù)據(jù)編程
  SD_CID_CSD_OVERWRITE               = 22,                              //CID/CSD覆蓋錯(cuò)誤
  SD_WP_ERASE_SKIP                   = 23,                              //只刪除了部分地址空間
  SD_CARD_ECC_DISABLED               = 24,                              //命令已在不使用內(nèi)部ECC的情況下執(zhí)行
  SD_ERASE_RESET                     = 25,                              //在執(zhí)行之前清除了擦除序列,因?yàn)槭盏搅艘粋€(gè)超出擦除序列的命令
  SD_AKE_SEQ_ERROR                   = 26,                              //身份驗(yàn)證順序錯(cuò)誤
  SD_INVALID_VOLTRANGE               = 27,
  SD_ADDR_OUT_OF_RANGE               = 28,
  SD_SWITCH_ERROR                    = 29,
  SD_SDIO_DISABLED                   = 30,
  SD_SDIO_FUNCTION_BUSY              = 31,
  SD_SDIO_FUNCTION_FAILED            = 32,
  SD_SDIO_UNKNOWN_FUNCTION           = 33,
  //標(biāo)準(zhǔn)錯(cuò)誤定義
  SD_INTERNAL_ERROR, 
  SD_NOT_CONFIGURED,
  SD_REQUEST_PENDING, 
  SD_REQUEST_NOT_APPLICABLE, 
  SD_INVALID_PARAMETER,  
  SD_UNSUPPORTED_FEATURE,  
  SD_UNSUPPORTED_HW,  
  SD_ERROR,  
  SD_OK = 0 
} SD_Error;      


//SD卡CSD寄存器數(shù)據(jù)      
typedef struct
{
  u8  CSDStruct;                                            //CSD結(jié)構(gòu)
  u8  SysSpecVersion;                                          //系統(tǒng)版本
  u8  Reserved1;                                            //保留
  u8  TAAC;                                              //數(shù)據(jù)讀取訪問(wèn)時(shí)間1
  u8  NSAC;                                              //在CLK期間的數(shù)據(jù)讀取訪問(wèn)時(shí)間2
  u8  MaxBusClkFrec;                                          //總線最高頻率
  u16 CardComdClasses;                                        //卡命令類
  u8  RdBlockLen;                                            //最大讀取數(shù)據(jù)塊長(zhǎng)度
  u8  PartBlockRead;                                          //允許讀取的部分塊
  u8  WrBlockMisalign;                                        //寫入塊未對(duì)準(zhǔn)
  u8  RdBlockMisalign;                                        //讀取塊未對(duì)準(zhǔn)
  u8  DSRImpl;                                            //DSR生效
  u8  Reserved2;                                            //保留 
  u32 DeviceSize;                                            //驅(qū)動(dòng)大小
  u8  MaxRdCurrentVDDMin;                                        //最大讀取流@ VDD最小
  u8  MaxRdCurrentVDDMax;                                        //最大讀取流@ VDD最大 
  u8  MaxWrCurrentVDDMin;                                        //最大寫入流@ VDD最小 
  u8  MaxWrCurrentVDDMax;                                        //最大寫入流@ VDD最大 
  u8  DeviceSizeMul;                                          //驅(qū)動(dòng)大小
  u8  EraseGrSize;                                          //擦除組大小
  u8  EraseGrMul;                                            //擦除組大小乘數(shù)
  u8  WrProtectGrSize;                                        //寫保護(hù)組大小
  u8  WrProtectGrEnable;                                        //寫保護(hù)組使能
  u8  ManDeflECC;                                            //制造商默認(rèn)ECC
  u8  WrSpeedFact;                                          //寫入速度因子
  u8  MaxWrBlockLen;                                          //最大寫入數(shù)據(jù)長(zhǎng)度
  u8  WriteBlockPaPartial;                                      //允許寫入的部分塊
  u8  Reserved3;                                            //保留
  u8  ContentProtectAppli;                                      //內(nèi)容保護(hù)程序
  u8  FileFormatGrouop;                                        //文件格式組
  u8  CopyFlag;                                            //復(fù)制標(biāo)志OTP 
  u8  PermWrProtect;                                          //永久寫保護(hù)
  u8  TempWrProtect;                                          //臨時(shí)寫保護(hù)
  u8  FileFormat;                                            //文件格式
  u8  ECC;                                              //ECC 代碼
  u8  CSD_CRC;                                            //CSD CRC 
  u8  Reserved4;                                            //總是1
} SD_CSD;   


//SD卡CID寄存器數(shù)據(jù)
typedef struct
{
  u8  ManufacturerID;                                          //制造商
  u16 OEM_AppliID;                                          //OEM/應(yīng)用程序ID
  u32 ProdName1;                                            //名稱部分1
  u8  ProdName2;                                            //名稱部分2
  u8  ProdRev;                                            //版本
  u32 ProdSN;                                              //序列號(hào)
  u8  Reserved1;                                            //保留1
  u16 ManufactDate;                                          //出廠日期
  u8  CID_CRC;                                            //CID CRC
  u8  Reserved2;                                            //總是1
} SD_CID;   
//SD卡狀態(tài)
typedef enum
{
  SD_CARD_READY                  = 0x00000001,
  SD_CARD_IDENTIFICATION         = 0x00000002,
  SD_CARD_STANDBY                = 0x00000003,
  SD_CARD_TRANSFER               = 0x00000004,
  SD_CARD_SENDING                = 0x00000005,
  SD_CARD_RECEIVING              = 0x00000006,
  SD_CARD_PROGRAMMING            = 0x00000007,
  SD_CARD_DISCONNECTED           = 0x00000008,
  SD_CARD_ERROR                  = 0x000000FF
}SDCardState;
//SD卡信息,包括CSD,CID等數(shù)據(jù)
typedef struct
{
  SD_CSD SD_csd;
  SD_CID SD_cid;
  long long CardCapacity;                                        //SD卡容量,單位:字節(jié),最大支持2^64字節(jié)大小的卡
  u32 CardBlockSize;                                          //SD卡塊大小  
  u16 RCA;                                                //卡相對(duì)地址
  u8 CardType;                                              //卡類型
} SD_CardInfo;
extern SD_CardInfo SDCardInfo;                                      //SD卡信息
//SDIO相關(guān)標(biāo)志位,拷貝自:stm32f4xx_sdio.h
#define SDIO_FLAG_CCRCFAIL                  0x00000001
#define SDIO_FLAG_DCRCFAIL                  0x00000002
#define SDIO_FLAG_CTIMEOUT                  0x00000004
#define SDIO_FLAG_DTIMEOUT                  0x00000008
#define SDIO_FLAG_TXUNDERR                  0x00000010
#define SDIO_FLAG_RXOVERR                   0x00000020
#define SDIO_FLAG_CMDREND                   0x00000040
#define SDIO_FLAG_CMDSENT                   0x00000080
#define SDIO_FLAG_DATAEND                   0x00000100
#define SDIO_FLAG_STBITERR                  0x00000200
#define SDIO_FLAG_DBCKEND                   0x00000400
#define SDIO_FLAG_CMDACT                    0x00000800
#define SDIO_FLAG_TXACT                     0x00001000
#define SDIO_FLAG_RXACT                     0x00002000
#define SDIO_FLAG_TXFIFOHE                  0x00004000
#define SDIO_FLAG_RXFIFOHF                  0x00008000
#define SDIO_FLAG_TXFIFOF                   0x00010000
#define SDIO_FLAG_RXFIFOF                   0x00020000
#define SDIO_FLAG_TXFIFOE                   0x00040000
#define SDIO_FLAG_RXFIFOE                   0x00080000
#define SDIO_FLAG_TXDAVL                    0x00100000
#define SDIO_FLAG_RXDAVL                    0x00200000
#define SDIO_FLAG_SDIOIT                    0x00400000
#define SDIO_FLAG_CEATAEND                  0x00800000
//SDIO 指令集
#define SD_CMD_GO_IDLE_STATE                       0
#define SD_CMD_SEND_OP_COND                        1
#define SD_CMD_ALL_SEND_CID                        2
#define SD_CMD_SET_REL_ADDR                        3                        //SD卡的SDIO_SEND_REL_ADDR
#define SD_CMD_SET_DSR                             4
#define SD_CMD_SDIO_SEN_OP_COND                    5
#define SD_CMD_HS_SWITCH                           6
#define SD_CMD_SEL_DESEL_CARD                      7
#define SD_CMD_HS_SEND_EXT_CSD                     8
#define SD_CMD_SEND_CSD                            9
#define SD_CMD_SEND_CID                            10
#define SD_CMD_READ_DAT_UNTIL_STOP                 11                        //SD卡不支持
#define SD_CMD_STOP_TRANSMISSION                   12
#define SD_CMD_SEND_STATUS                         13
#define SD_CMD_HS_BUSTEST_READ                     14
#define SD_CMD_GO_INACTIVE_STATE                   15
#define SD_CMD_SET_BLOCKLEN                        16
#define SD_CMD_READ_SINGLE_BLOCK                   17
#define SD_CMD_READ_MULT_BLOCK                     18
#define SD_CMD_HS_BUSTEST_WRITE                    19
#define SD_CMD_WRITE_DAT_UNTIL_STOP                20 
#define SD_CMD_SET_BLOCK_COUNT                     23 
#define SD_CMD_WRITE_SINGLE_BLOCK                  24
#define SD_CMD_WRITE_MULT_BLOCK                    25
#define SD_CMD_PROG_CID                            26
#define SD_CMD_PROG_CSD                            27
#define SD_CMD_SET_WRITE_PROT                      28
#define SD_CMD_CLR_WRITE_PROT                      29
#define SD_CMD_SEND_WRITE_PROT                     30
#define SD_CMD_SD_ERASE_GRP_START                  32                        //設(shè)置要擦除的第一個(gè)寫塊的地址SD卡獨(dú)有
#define SD_CMD_SD_ERASE_GRP_END                    33                        //設(shè)置要擦除的連續(xù)范圍的最后一個(gè)寫塊的地址SD卡獨(dú)有
#define SD_CMD_ERASE_GRP_START                     35                        //設(shè)置要擦除的第一個(gè)寫塊的地址MMC card 3.31


#define SD_CMD_ERASE_GRP_END                       36                        //設(shè)置要擦除的連續(xù)范圍的最后一個(gè)寫塊的地址MMC card 3.31


#define SD_CMD_ERASE                               38
#define SD_CMD_FAST_IO                             39                        //SD卡不支持
#define SD_CMD_GO_IRQ_STATE                        40                        //SD卡不支持
#define SD_CMD_LOCK_UNLOCK                         42
#define SD_CMD_APP_CMD                             55
#define SD_CMD_GEN_CMD                             56
#define SD_CMD_NO_CMD                              64


#define SD_CMD_APP_SD_SET_BUSWIDTH                 6                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_STAUS                        13                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS        22                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_OP_COND                      41                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_SET_CLR_CARD_DETECT          42                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_SEND_SCR                     51                        //SD卡獨(dú)有
#define SD_CMD_SDIO_RW_DIRECT                      52                        //SD卡IO獨(dú)有
#define SD_CMD_SDIO_RW_EXTENDED                    53                        //SD卡IO獨(dú)有


#define SD_CMD_SD_APP_GET_MKB                      43                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_GET_MID                      44                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_SET_CER_RN1                  45                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_GET_CER_RN2                  46                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_SET_CER_RES2                 47                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_GET_CER_RES1                 48                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_SECURE_READ_MULTIPLE_BLOCK   18                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_SECURE_WRITE_MULTIPLE_BLOCK  25                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_SECURE_ERASE                 38                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_CHANGE_SECURE_AREA           49                        //SD卡獨(dú)有
#define SD_CMD_SD_APP_SECURE_WRITE_MKB             48                        //SD卡獨(dú)有
//支持的SD卡定義
#define SDIO_STD_CAPACITY_SD_CARD_V1_1             0x00000000
#define SDIO_STD_CAPACITY_SD_CARD_V2_0             0x00000001
#define SDIO_HIGH_CAPACITY_SD_CARD                 0x00000002
#define SDIO_MULTIMEDIA_CARD                       0x00000003
#define SDIO_SECURE_DIGITAL_IO_CARD                0x00000004
#define SDIO_HIGH_SPEED_MULTIMEDIA_CARD            0x00000005
#define SDIO_SECURE_DIGITAL_IO_COMBO_CARD          0x00000006
#define SDIO_HIGH_CAPACITY_MMC_CARD                0x00000007
//SDIO相關(guān)參數(shù)定義
#define NULL 0
#define SDIO_STATIC_FLAGS               0x000005FF
#define SDIO_CMD0TIMEOUT                0x00010000    
#define SDIO_DATATIMEOUT                0xFFFFFFFF    
#define SDIO_FIFO_Address               0x40018080
//Mask for errors Card Status R1 OCR Register  
#define SD_OCR_ADDR_OUT_OF_RANGE        0x80000000
#define SD_OCR_ADDR_MISALIGNED          0x40000000
#define SD_OCR_BLOCK_LEN_ERR            0x20000000
#define SD_OCR_ERASE_SEQ_ERR            0x10000000
#define SD_OCR_BAD_ERASE_PARAM          0x08000000
#define SD_OCR_WRITE_PROT_VIOLATION     0x04000000
#define SD_OCR_LOCK_UNLOCK_FAILED       0x01000000
#define SD_OCR_COM_CRC_FAILED           0x00800000
#define SD_OCR_ILLEGAL_CMD              0x00400000
#define SD_OCR_CARD_ECC_FAILED          0x00200000
#define SD_OCR_CC_ERROR                 0x00100000
#define SD_OCR_GENERAL_UNKNOWN_ERROR    0x00080000
#define SD_OCR_STREAM_READ_UNDERRUN     0x00040000
#define SD_OCR_STREAM_WRITE_OVERRUN     0x00020000
#define SD_OCR_CID_CSD_OVERWRIETE       0x00010000
#define SD_OCR_WP_ERASE_SKIP            0x00008000
#define SD_OCR_CARD_ECC_DISABLED        0x00004000
#define SD_OCR_ERASE_RESET              0x00002000
#define SD_OCR_AKE_SEQ_ERROR            0x00000008
#define SD_OCR_ERRORBITS                0xFDFFE008
//Masks for R6 Response 
#define SD_R6_GENERAL_UNKNOWN_ERROR     0x00002000
#define SD_R6_ILLEGAL_CMD               0x00004000
#define SD_R6_COM_CRC_FAILED            0x00008000


#define SD_VOLTAGE_WINDOW_SD            0x80100000
#define SD_HIGH_CAPACITY                0x40000000
#define SD_STD_CAPACITY                 0x00000000
#define SD_CHECK_PATTERN                0x000001AA
#define SD_VOLTAGE_WINDOW_MMC           0x80FF8000


#define SD_MAX_VOLT_TRIAL               0x0000FFFF
#define SD_ALLZERO                      0x00000000


#define SD_WIDE_BUS_SUPPORT             0x00040000
#define SD_SINGLE_BUS_SUPPORT           0x00010000
#define SD_CARD_LOCKED                  0x02000000
#define SD_CARD_PROGRAMMING             0x00000007
#define SD_CARD_RECEIVING               0x00000006
#define SD_DATATIMEOUT                  0xFFFFFFFF
#define SD_0TO7BITS                     0x000000FF
#define SD_8TO15BITS                    0x0000FF00
#define SD_16TO23BITS                   0x00FF0000
#define SD_24TO31BITS                   0xFF000000
#define SD_MAX_DATA_LENGTH              0x01FFFFFF


#define SD_HALFFIFO                     0x00000008
#define SD_HALFFIFOBYTES                0x00000020
//Command Class Supported  
#define SD_CCCC_LOCK_UNLOCK             0x00000080
#define SD_CCCC_WRITE_PROT              0x00000040
#define SD_CCCC_ERASE                   0x00000020                                 
//CMD8指令
#define SDIO_SEND_IF_COND               0x00000008
/*********************************************************************************************************
                  函    數(shù)    列    表
*********************************************************************************************************/
SD_Error SD_Init( void ) ;                                        //初始化SD卡
u8 SD_ReadDisk( u8*buf, u32 sector, u8 cnt ) ;                              //讀SD卡,fatfs/usb調(diào)用
u8 SD_WriteDisk( u8*buf, u32 sector, u8 cnt ) ;                              //寫SD卡,fatfs/usb調(diào)用


#endif

(2)創(chuàng)建sdio_sdcard.c文件,并輸入以下代碼。

#include "sdio_sdcard.h"
#include "string.h"


SD_CardInfo SDCardInfo ;                                        //SD卡信息
u8 CardType=SDIO_STD_CAPACITY_SD_CARD_V1_1 ;                              //SD卡類型
/***************************************************
Name    :SDIO_Clock_Set
Function  :SDIO發(fā)送命令函數(shù)
Paramater  :
      cmdindex:命令索引,低六位有效
      waitrsp:期待的相應(yīng)
        00/10:無(wú)響應(yīng)
        01:短響應(yīng)
        11:長(zhǎng)響應(yīng)
      arg:參數(shù)
Return    :錯(cuò)誤代碼
***************************************************/
void SDIO_Send_Cmd( u8 cmdindex, u8 waitrsp, u32 arg )
{      
  u32 tmpreg ;
  SDIO->ARG = arg ;
  tmpreg = SDIO->CMD ;
  tmpreg &= 0xFFFFF800 ;                                        //清除index和waitrsp
  tmpreg |= cmdindex&0X3F ;                                      //設(shè)置新的index
  tmpreg |= waitrsp<<6 ;                                        //設(shè)置新的wait rsp
  tmpreg |= 0<<8 ;                                          //無(wú)等待
  tmpreg |= 1<<10 ;                                          //命令通道狀態(tài)機(jī)使能
  SDIO->CMD = tmpreg ;
}
/***************************************************
Name    :SDIO_Send_Data_Cfg
Function  :SDIO發(fā)送數(shù)據(jù)配置函數(shù)
Paramater  :
      datatimeout:超時(shí)時(shí)間設(shè)置
      datalen:傳輸數(shù)據(jù)長(zhǎng)度,低25位有效,必須為塊大小的整數(shù)倍
      blksize:塊大小.實(shí)際大小為:2^blksize字節(jié)
      dir:數(shù)據(jù)傳輸方向
        0:控制器到卡
        1:卡到控制器
Return    :錯(cuò)誤代碼
***************************************************/
void SDIO_Send_Data_Cfg( u32 datatimeout, u32 datalen, u8 blksize, u8 dir )
{
  u32 tmpreg;
  SDIO->DTIMER = datatimeout ;
  SDIO->DLEN = datalen&0x1FFFFFF ;                                  //低25位有效
  tmpreg = SDIO->DCTRL ; 
  tmpreg &= 0xFFFFFF08 ;                                        //清除之前的設(shè)置
  tmpreg |= blksize<<4 ;                                        //設(shè)置塊大小
  tmpreg |= 0<<2 ;                                          //塊數(shù)據(jù)傳輸
  tmpreg |= ( dir&0x01 )<<1 ;                                      //方向控制
  tmpreg |= 1<<0 ;                                          //數(shù)據(jù)傳輸使能,DPSM狀態(tài)機(jī)
  SDIO->DCTRL = tmpreg ;
}
/***************************************************
Name    :SDIO_Clock_Set
Function  :SDIO時(shí)鐘初始化設(shè)置
Paramater  :
      clkdiv:時(shí)鐘分頻系數(shù)
Return    :錯(cuò)誤代碼
***************************************************/
void SDIO_Clock_Set( u8 clkdiv )
{
  u32 tmpreg = SDIO->CLKCR ;
  tmpreg &= 0xFFFFFF00 ;
  tmpreg |= clkdiv;
  SDIO->CLKCR = tmpreg ;
}
/***************************************************
Name    :CmdError
Function  :檢查CMD0的執(zhí)行狀態(tài)
Paramater  :None
Return    :錯(cuò)誤代碼
***************************************************/
SD_Error CmdError()
{
  SD_Error errorstatus = SD_OK ;
  u32 timeout=SDIO_CMD0TIMEOUT ;
  while( timeout-- )
  {
    //命令已發(fā)送(無(wú)需響應(yīng))
    if( SDIO->STA&( 1<<7 ) )
      break ;
  }
  if( timeout==0 )
    return SD_CMD_RSP_TIMEOUT ;
  SDIO->ICR = 0x5FF ;                                          //清除標(biāo)記
  return errorstatus ;
}
/***************************************************
Name    :CmdResp7Error
Function  :檢查R7響應(yīng)的錯(cuò)誤狀態(tài)
Paramater  :None
Return    :錯(cuò)誤代碼
***************************************************/
SD_Error CmdResp7Error()
{
  u32 status ;
  u32 timeout = 0x00010000 ;
   while( timeout-- )
  {
    status = SDIO->STA ;
    if( ( status&0x45 )!=0 )                                    //等待接收到應(yīng)答
      break ;
  }
  //響應(yīng)超時(shí)
   if( ( timeout==0 )||( ( status&0x04 )==0x04 ) )
  {
    //當(dāng)前卡不是2.0兼容卡,或者不支持設(shè)定的電壓范圍
    SDIO->ICR |= 1<<2 ;                                        //清除命令響應(yīng)超時(shí)標(biāo)志
    return SD_CMD_RSP_TIMEOUT ;
  }
  //成功接收到響應(yīng)
  if( ( status&0x40 )==0x40 )
    SDIO->ICR |= 1<<6 ;                                        //清除響應(yīng)標(biāo)志
  return SD_OK ;
}
/***************************************************
Name    :CmdResp1Error
Function  :檢查R1響應(yīng)的錯(cuò)誤狀態(tài)
Paramater  :
      cmd:當(dāng)前命令
Return    :錯(cuò)誤代碼
***************************************************/
SD_Error CmdResp1Error( u8 cmd )
{    
     u32 status ;
  while( 1 )
  {
    status = SDIO->STA ;
    if( ( status&0x45 )!=0 )                                    //等待接收到應(yīng)答
      break ;
  }
  //響應(yīng)超時(shí)
  if( ( status&0x04 )==0x04 )
  {
     SDIO->ICR |= 1<<2 ;                                        //清除命令響應(yīng)超時(shí)標(biāo)志
    return SD_CMD_RSP_TIMEOUT ;
  }
  //CRC錯(cuò)誤
   if( ( status&0x01 )==0x01 )
  {
     SDIO->ICR |= 1<<0;                                        //清除標(biāo)志
    return SD_CMD_CRC_FAIL;
  }
  if( SDIO->RESPCMD!=cmd )
    return SD_ILLEGAL_CMD ;                                      //命令不匹配
    SDIO->ICR = 0x5FF ;                                          //清除標(biāo)記
  return ( SD_Error )( SDIO->RESP1&0xFDFFE008 ) ;                            //返回卡響應(yīng)
}
/***************************************************
Name    :CmdResp3Error
Function  :檢查R3響應(yīng)的錯(cuò)誤狀態(tài)
Paramater  :None
Return    :錯(cuò)誤代碼
***************************************************/
SD_Error CmdResp3Error()
{
  u32 status ;             
   while( 1 )
  {
    status = SDIO->STA ;
    if( ( status&0x45 )!=0 )                                     //等待接收到應(yīng)答
      break ;
  }
  //響應(yīng)超時(shí)
   if( ( status&0x04 )==0x04 )
  {
    SDIO->ICR |= 1<<2 ;                                        //清除命令響應(yīng)超時(shí)標(biāo)志
    return SD_CMD_RSP_TIMEOUT ;
  }
     SDIO->ICR = 0x5FF ;                                          //清除標(biāo)記
   return SD_OK ;
}
/***************************************************
Name    :CmdResp2Error
Function  :檢查R2響應(yīng)的錯(cuò)誤狀態(tài)
Paramater  :None
Return    :錯(cuò)誤代碼
***************************************************/
SD_Error CmdResp2Error()
{
  u32 status ;
  u32 timeout = 0x00010000 ;
   while( timeout-- )
  {
    status = SDIO->STA ;
    if( ( status&0x45 )!=0 )                                    //接收到R2響應(yīng)
      break ;
  }
  //響應(yīng)超時(shí)
    if( ( timeout==0 )||( ( status&0x04 )==0x04 ) )
  {
    SDIO->ICR |= 1<<2 ;                                        //清除命令響應(yīng)超時(shí)標(biāo)志
    return SD_CMD_RSP_TIMEOUT ;
  }
  //CRC錯(cuò)誤
  if( ( status&0x01 )==0x01 )
  {
    SDIO->ICR |= 1<<0 ;                                        //清除響應(yīng)標(biāo)志
    return SD_CMD_CRC_FAIL ;
   }
  SDIO->ICR = 0x5FF ;                                          //清除標(biāo)記
   return SD_OK ;
}
/***************************************************
Name    :CmdResp6Error
Function  :檢查R6響應(yīng)的錯(cuò)誤狀態(tài)
Paramater  :
      cmd:之前發(fā)送的命令
      prca:卡返回的RCA地址
Return    :錯(cuò)誤代碼
***************************************************/
SD_Error CmdResp6Error( u8 cmd, u16 *prca )
{
  SD_Error errorstatus=SD_OK ;
  u32 rspr1, status;
   while(1)
  {
    status = SDIO->STA ;
    //CRC錯(cuò)誤/命令響應(yīng)超時(shí)/已經(jīng)收到響應(yīng)(CRC校驗(yàn)成功)
    if( status&( (1<<0)|(1<<2)|(1<<6) ) )
      break ;
  }
  //響應(yīng)超時(shí)
  if( status&( 1<<2 ) )
  {
     SDIO->ICR |= 1<<2 ;                                        //清除命令響應(yīng)超時(shí)標(biāo)志
    return SD_CMD_RSP_TIMEOUT ;
  }
  //CRC錯(cuò)誤
  if( status&1<<0 )
  {
    SDIO->ICR |= 1<<0 ;                                        //清除響應(yīng)標(biāo)志
     return SD_CMD_CRC_FAIL ;
  }
  //判斷是否響應(yīng)cmd命令
  if( SDIO->RESPCMD!=cmd )
     return SD_ILLEGAL_CMD ;
  SDIO->ICR = 0x5FF ;                                          //清除所有標(biāo)記
  rspr1 = SDIO->RESP1 ;                                        //得到響應(yīng)
  if( SD_ALLZERO==( rspr1&( SD_R6_GENERAL_UNKNOWN_ERROR|SD_R6_ILLEGAL_CMD|SD_R6_COM_CRC_FAILED ) ) )
  {
    *prca = ( u16 )( rspr1>>16 ) ;                                  //右移16位得到,rca
    return errorstatus ;
  }
     if( rspr1&SD_R6_GENERAL_UNKNOWN_ERROR )
    return SD_GENERAL_UNKNOWN_ERROR ;
     if( rspr1&SD_R6_ILLEGAL_CMD )
    return SD_ILLEGAL_CMD ;
     if( rspr1&SD_R6_COM_CRC_FAILED )
    return SD_COM_CRC_FAILED ;
  return errorstatus ;
}
/***************************************************
Name    :SDIO_IRQHandler
Function  :SDIO中斷服務(wù)函數(shù)
Paramater  :None
Return    :錯(cuò)誤代碼
***************************************************/
void SDIO_IRQHandler()
{
   //接收完成中斷
  if( SDIO->STA&( 1<<8 ) )
  {
    SDIO_Send_Cmd( SD_CMD_STOP_TRANSMISSION, 1, 0 ) ;                        //發(fā)送CMD12,結(jié)束傳輸
     SDIO->ICR |= 1<<8 ;                                        //清除完成中斷標(biāo)記
    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //關(guān)閉相關(guān)中斷
  }
  //數(shù)據(jù)CRC錯(cuò)誤
   if( SDIO->STA&( 1<<1 ) )
  {
    SDIO->ICR |= 1<<1 ;                                        //清除中斷標(biāo)記
    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //關(guān)閉相關(guān)中斷
  }
  //數(shù)據(jù)超時(shí)錯(cuò)誤
   if( SDIO->STA&( 1<<3 ) )
  {
    SDIO->ICR |= 1<<3 ;                                        //清除中斷標(biāo)記
    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //關(guān)閉相關(guān)中斷
  }
  //FIFO上溢錯(cuò)誤
    if( SDIO->STA&( 1<<5 ) )
  {
    SDIO->ICR |= 1<<5 ;                                        //清除中斷標(biāo)記
    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //關(guān)閉相關(guān)中斷
  }
  //FIFO下溢錯(cuò)誤
     if( SDIO->STA&( 1<<4 ) )
  {
    SDIO->ICR |= 1<<4 ;                                        //清除中斷標(biāo)記
    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //關(guān)閉相關(guān)中斷
  }
  //起始位錯(cuò)誤
  if( SDIO->STA&( 1<<9 ) )
  {
    SDIO->ICR |= 1<<9 ;                                        //清除中斷標(biāo)記
    SDIO->MASK &= ~( ( 1<<1 )|( 1<<3 )|( 1<<8 )|( 1<<14 )|( 1<<15 )|( 1<<4 )|( 1<<5 )|( 1<<9 ) ) ;  //關(guān)閉相關(guān)中斷
  }
}
/***************************************************
Name    :SD_PowerON
Function  :卡上電
Paramater  :None
Return    :錯(cuò)誤代碼
***************************************************/
SD_Error SD_PowerON()
{
  u8 i=0 ;
  SD_Error errorstatus=SD_OK ;
  u32 response=0, count=0, validvoltage=0 ;
  u32 SDType=SD_STD_CAPACITY ;
  //配置CLKCR寄存器
  SDIO->CLKCR = 0 ;                                          //清空CLKCR之前的設(shè)置
  SDIO->CLKCR |= 0<<9 ;                                        //非省電模式
  SDIO->CLKCR |= 0<<10 ;                                        //關(guān)閉旁路,CK根據(jù)分頻設(shè)置輸出
  SDIO->CLKCR |= 0<<11 ;                                        //1位數(shù)據(jù)寬度
  SDIO->CLKCR |= 0<<13 ;                                        //SDIOCLK上升沿產(chǎn)生SDIOCK
  SDIO->CLKCR |= 0<<14 ;                                        //關(guān)閉硬件流控制
  SDIO_Clock_Set( SDIO_INIT_CLK_DIV ) ;                                //設(shè)置時(shí)鐘頻率(初始化的時(shí)候,不能超過(guò)400Khz)
  SDIO->POWER = 0x03 ;                                        //上電狀態(tài),開(kāi)啟卡時(shí)鐘
  SDIO->CLKCR |= 1<<8 ;                                        //SDIOCK使能
  for( i=0; i<74; i++ )
  {
    SDIO_Send_Cmd( SD_CMD_GO_IDLE_STATE, 0, 0 ) ;                          //發(fā)送CMD0進(jìn)入IDLE STAGE模式命令
    errorstatus = CmdError() ;
    if( errorstatus==SD_OK )
      break ;
  }
  //返回錯(cuò)誤狀態(tài)
  if( errorstatus )
    return errorstatus ;
  SDIO_Send_Cmd( SDIO_SEND_IF_COND, 1, SD_CHECK_PATTERN ) ;                      //發(fā)送CMD8,短響應(yīng),檢查SD卡接口特性
  errorstatus = CmdResp7Error() ;                                    //等待R7響應(yīng)
  //R7響應(yīng)正常
  if( errorstatus==SD_OK )
  {
    CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0 ;                            //SD 2.0卡
    SDType = SD_HIGH_CAPACITY ;                                    //高容量卡
  }
  SDIO_Send_Cmd( SD_CMD_APP_CMD, 1, 0 ) ;                                //發(fā)送CMD55,短響應(yīng)
  errorstatus = CmdResp1Error( SD_CMD_APP_CMD ) ;                            //等待R1響應(yīng)
  //SD2.0/SD 1.1,否則為MMC卡
  if( errorstatus==SD_OK )
  {
    //SD卡,發(fā)送ACMD41 SD_APP_OP_COND,參數(shù)為:0x80100000
    while( ( !validvoltage )&&( count

(3)創(chuàng)建1.c文件,并輸入以下代碼。

#include "sys.h"
#include "delay.h"
#include "usart1.h"
#include "lcd.h"
#include "sdio_sdcard.h"


int main()
{
  u8 Str[ 30 ] ;
  u16 temp ;
   STM32_Clock_Init( 9 ) ;                                        //系統(tǒng)時(shí)鐘設(shè)置
  SysTick_Init( 72 ) ;                                        //延時(shí)初始化
  USART1_Init( 72, 115200 ) ;                                      //串口初始化為115200
  LCD_Init() ;                                            //初始化LCD
  while( SD_Init() ) ;                                        //初始化SD卡
  temp = SDCardInfo.CardCapacity>>20 ;                                //單位換算
  sprintf( ( char * )Str, "SD Size: %4d MB", temp ) ;
  LCD_ShowString( 30, 170, Str ) ;                                  //顯示SD卡容量
   while(1)
  {

  }
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 存儲(chǔ)器
    +關(guān)注

    關(guān)注

    38

    文章

    7401

    瀏覽量

    163383
  • 嵌入式系統(tǒng)
    +關(guān)注

    關(guān)注

    41

    文章

    3531

    瀏覽量

    128980
  • SD卡
    +關(guān)注

    關(guān)注

    2

    文章

    554

    瀏覽量

    63676
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【紫光同創(chuàng)國(guó)產(chǎn)FPGA教程】【第八章】SD讀寫實(shí)驗(yàn)

    SD是現(xiàn)在嵌入式設(shè)備重要的存儲(chǔ)模塊,內(nèi)部集成了nand flash控制器,方便了主機(jī)的的管理。本實(shí)驗(yàn)主要是練習(xí)對(duì)sd的扇區(qū)進(jìn)行
    的頭像 發(fā)表于 02-05 11:35 ?8227次閱讀
    【紫光同創(chuàng)國(guó)產(chǎn)FPGA教程】【第八章】<b class='flag-5'>SD</b><b class='flag-5'>卡</b><b class='flag-5'>讀寫實(shí)驗(yàn)</b>

    #硬聲創(chuàng)作季 #FPGA Zedboard教程-40.1 SD讀寫實(shí)驗(yàn)-1

    fpgaSDSDsd存儲(chǔ)
    水管工
    發(fā)布于 :2022年11月04日 03:29:11

    #硬聲創(chuàng)作季 #FPGA Zedboard教程-40.1 SD讀寫實(shí)驗(yàn)-2

    fpgaSDSDsd存儲(chǔ)
    水管工
    發(fā)布于 :2022年11月04日 03:29:34

    #硬聲創(chuàng)作季 #FPGA Zedboard教程-40.1 SD讀寫實(shí)驗(yàn)-3

    fpgaSDSDsd存儲(chǔ)
    水管工
    發(fā)布于 :2022年11月04日 03:29:53

    #硬聲創(chuàng)作季 #FPGA Zedboard教程-40.1 SD讀寫實(shí)驗(yàn)-4

    fpgaSDSDsd存儲(chǔ)
    水管工
    發(fā)布于 :2022年11月04日 03:30:17

    #硬聲創(chuàng)作季 #FPGA Zedboard教程-40.1 SD讀寫實(shí)驗(yàn)-5

    fpgaSDSDsd存儲(chǔ)
    水管工
    發(fā)布于 :2022年11月04日 03:30:40

    #硬聲創(chuàng)作季 #FPGA Zedboard教程-40.2 SD讀寫實(shí)驗(yàn)

    fpgaSDSDsd存儲(chǔ)
    水管工
    發(fā)布于 :2022年11月04日 03:30:59

    32 第14講--Mirco SD讀寫實(shí)驗(yàn) - 第1節(jié)

    DDR3數(shù)據(jù)串口通信代碼狀態(tài)機(jī)邏輯分析儀
    充八萬(wàn)
    發(fā)布于 :2023年08月19日 04:32:06

    32 第14講--Mirco SD讀寫實(shí)驗(yàn) - 第2節(jié)

    DDR3數(shù)據(jù)串口通信代碼狀態(tài)機(jī)邏輯分析儀
    充八萬(wàn)
    發(fā)布于 :2023年08月19日 04:32:57

    32 第14講--Mirco SD讀寫實(shí)驗(yàn) - 第3節(jié)

    DDR3數(shù)據(jù)串口通信代碼狀態(tài)機(jī)邏輯分析儀
    充八萬(wàn)
    發(fā)布于 :2023年08月19日 04:33:47

    32 第14講--Mirco SD讀寫實(shí)驗(yàn) - 第4節(jié) #硬聲創(chuàng)作季

    DDR3數(shù)據(jù)串口通信代碼狀態(tài)機(jī)邏輯分析儀
    充八萬(wàn)
    發(fā)布于 :2023年08月19日 04:40:29

    32 第14講--Mirco SD讀寫實(shí)驗(yàn) - 第4節(jié)

    DDR3數(shù)據(jù)串口通信代碼狀態(tài)機(jī)邏輯分析儀
    充八萬(wàn)
    發(fā)布于 :2023年08月19日 07:26:13

    arduino學(xué)習(xí)筆記18 - SD讀寫實(shí)驗(yàn)

    本次實(shí)驗(yàn)使用arduino驅(qū)動(dòng)SD,在SD中進(jìn)行文件讀寫。需要說(shuō)明的是arduino的
    發(fā)表于 10-24 10:09

    SD讀寫實(shí)驗(yàn)

    飛思卡爾現(xiàn)在的NXP的ARM9芯片i.mx283在wince上的例程。
    發(fā)表于 04-22 14:06 ?3次下載

    SD基礎(chǔ)讀寫實(shí)驗(yàn)詳解

    SD是嵌入式系統(tǒng)中最常見(jiàn)的存儲(chǔ)器,不僅容量可以做的很大,并且接口通用,支持SPI/SDIO驅(qū)動(dòng),尺寸可供選擇,能滿足不同應(yīng)用的要求。STM32F1系列自帶了標(biāo)準(zhǔn)的4位SDIO接口,最高通信速度可達(dá)24MHz,最高每秒能傳輸12M字節(jié)的數(shù)據(jù)。
    的頭像 發(fā)表于 01-31 18:01 ?2521次閱讀
    <b class='flag-5'>SD</b><b class='flag-5'>卡</b>基礎(chǔ)<b class='flag-5'>讀寫實(shí)驗(yàn)</b>詳解