現(xiàn)在我們手機(jī)的內(nèi)存卡多為Micro SD卡,又叫TF卡,所以Micro SD卡比SD卡常見。自己曾經(jīng)也想寫寫SD卡的讀取程序,但又不想特地再去買個SD卡,這時想起手機(jī)內(nèi)存卡不是和SD卡很像嗎?在網(wǎng)上查了以后發(fā)現(xiàn)SD卡和Micro SD卡其實(shí)也就大小和引腳不一樣,它們的操作其實(shí)是一樣的,所以網(wǎng)上的SD卡讀寫代碼其實(shí)可以直接拿來用。關(guān)于SD卡和Micro SD卡的引腳定義和不同可見下兩表:
我們可以發(fā)現(xiàn)Micro SD卡只有8個引腳是因?yàn)楸萐D卡少了一個Vss。當(dāng)然你也可以買個卡套套在Micro SD卡上,這樣一來大小就和SD卡一樣大,這時候卡套上的9個引腳就和SD卡一樣了,你可以完全當(dāng)做SD卡來操作。
spi下電路的連接非常簡單,接上電源線Vdd和地線Vss,再接上spi的CS,SCLK,DI(MOSI)和DO(MISO)就可以了,其他引腳可以放空。注意SD卡的電源和操作電壓都為2.7-3.6V,5V的單片機(jī)要進(jìn)行電平轉(zhuǎn)換或串電阻限流。還有記得SD卡的CS,SCLKh和DI要用10~100K的電阻上拉。我是套了卡套接的電路,因?yàn)镸icro SD卡的引腳太密了,不好焊接,SD卡相對引腳好焊。因?yàn)闆]有卡座,而且也沒專門的PCB我就直接焊到卡套上,誒犧牲了一個卡套。下面是我自己畫的電路圖:
上面Micro SD卡的硬件電路就好了,下面我們講講Micro SD卡的軟件驅(qū)動和指令集。
SD卡的命令格式如下,6字節(jié)共48位,傳輸時最高位(MSB)先傳輸:
SD卡的command(命令)占6 bit,一般叫CMDx或ACMDx,比如CMD1就是1,CMD13就是13,ACMD41就是41,依此類推。Command Argument(命令參數(shù))占4 byte,并不是所有命令都有參數(shù),沒有參數(shù)的話該位一般就用置0。最后一個字節(jié)由7 bit CRC校驗(yàn)位和1 bit停止位組成。在SPI模式下,CRC是被忽略的,可以都置1或置0.但是發(fā)送CMD0時要記得加上CRC,即最后1字節(jié)為0x95(因?yàn)榘l(fā)送CMD0時還未進(jìn)入SPI模式,PS:CMD8也要,但一般大家都把發(fā)送CMD8省略了)。
每次發(fā)送完一次命令后,SD卡都會有回應(yīng)。SD卡的回應(yīng)有多種格式,1字節(jié)的R1,2字節(jié)的R2等,不過一般在SPI模式中我們只用到R1,下面介紹R1的格式:
關(guān)于SD卡SPI和command的發(fā)送要注意以下幾點(diǎn):
3.在SD卡的Din沒有數(shù)據(jù)寫入時,應(yīng)使Din保持高電平。關(guān)于這一點(diǎn)我可吃透了苦頭,本來也記得要保持高電平的,結(jié)果不知怎的鬼使神差的置0拉低了。結(jié)果程序出現(xiàn)了各種奇怪的貌似偶然的錯誤,比如連續(xù)兩次復(fù)位會有一次失敗,單步調(diào)試成功全速運(yùn)行又會失敗。總之在這個過程中我對時序進(jìn)行各種改變,每次解決一個問題后又會有新的問題出現(xiàn),多少次動搖了我對MicroSD卡和SD卡的操作是一樣的這個看法。因?yàn)檫@個低級的錯誤耽誤了我三四天,看來細(xì)心很重要??!我已經(jīng)不止一次因?yàn)椴患?xì)心浪費(fèi)大量時間了,希望大家也引以為戒。
好了,現(xiàn)在SD卡的命令和回應(yīng)清楚了,我們下面講講SD卡的復(fù)位,初始化和讀寫方法。
復(fù)位方法:
1.拉高CS,發(fā)送至少74個clk周期來使SD卡達(dá)到正常工作電壓和進(jìn)行同步
2.選低CS,發(fā)送CMD0,需要收到回應(yīng)0x01表示成功進(jìn)入idle狀態(tài)
3.拉高CS,發(fā)送8個時鐘
復(fù)位時序圖:
初始化:
復(fù)位成功后,SD卡就進(jìn)入了SPI模式,接著應(yīng)該進(jìn)行初始化。初始化說白了有兩種方法:(1)發(fā)送CMD1,(2)發(fā)送CMD55+ACMD41。我從網(wǎng)上查的資料可以看到這種說法:如果是MMC卡就發(fā)CMD1,SD卡則發(fā)CMD55+ACMD41。但是關(guān)于Micro SD卡要發(fā)哪種卻講的不太清楚,網(wǎng)上用這兩種方法都有人成功過,但有的都成功不了。我自己也碰到了這種問題,剛開始拿了自己手機(jī)上的寫著Nokia的2GB的Micro SD卡(應(yīng)該是雜牌的)初始化了兩天也沒成功,快要放棄的時候想起來為什么不換張試試呢,于是就找室友借了他的手機(jī)內(nèi)存卡,是2GB的Apacer的Micro SD卡(當(dāng)然也可能是雜牌的,室友買那卡的地方一般都是賣各種廉價電子產(chǎn)品的,大家都知道是雜牌的),結(jié)果一試就成功了。后來我用了令一種方法發(fā)現(xiàn)也可以初始化,也就是說兩種方法都可以初始化成功。但我的那種怎么就不行呢?難道不是所有Micro SD卡都支持SPI模式。我在網(wǎng)上百度了半天也不能確定是不是所有Micro SD卡都支持SPI模式。但我想,現(xiàn)在Micro SD卡的生產(chǎn)公司很多,而且你也并不能保證你的Micro SD卡不是雜牌的。你并不知道生產(chǎn)廠家進(jìn)行了那些改變,因?yàn)榇_實(shí)有些廠家生產(chǎn)的SD卡精簡了一些命令。所以初始化的時候建議兩種都試一下,不過我記得SD卡的說明書上推薦使用第二種方法。
下面是初始化方法:
(1)使用CMD1
發(fā)送CMD1,收到0x00表示成功
時序圖如下:
(2)使用CMD55+ACMD41
1.發(fā)送CMD55(表示使用ACMDx類命令),收到0x01
2.發(fā)送ACMD41,收到0x00表示成功
記住SD卡的初始化速度不能大于400kHz,所以一開始復(fù)位和初始化時spi的速率要設(shè)置低一點(diǎn)。
讀單塊和多塊:
SD卡讀單塊和多塊的命令分別為CMD17和CMD18,他們的參數(shù)即要讀的區(qū)域的開始地址。因?yàn)榭紤]到一般SD卡的讀寫要求地址對齊,所以一般我們都將地址轉(zhuǎn)為塊,并以扇區(qū)(塊)(512Byte)為單位進(jìn)行讀寫,比如讀扇區(qū)0參數(shù)就為0,讀扇區(qū)1參數(shù)就為1<<9(即地址512),讀扇區(qū)2參數(shù)就為2<<9(即地址1024),依此類推。
讀單塊方法:
1.發(fā)送CMD17,收到0x00表示成功
2.連續(xù)讀直到讀到開始字節(jié)0xFE
3.讀512個字節(jié)
4.讀兩個CRC字節(jié)
讀單塊時序圖:
讀多塊方法:
1.發(fā)送CMD18讀,收到0x00表示成功
2.連續(xù)讀直到讀到開始字節(jié)0xFE
3.讀512字節(jié)
4.讀兩個CRC字節(jié)
5.如果還想讀下一扇區(qū),重復(fù)2-4
6.發(fā)送CMD12來停止讀多塊操作
寫單塊和多塊:
SD卡用CMD24和CMD25來寫單塊和多塊,參數(shù)的定義和讀操作是一樣的。
寫單塊方法:
1.發(fā)送CMD24,收到0x00表示成功
2.發(fā)送若干時鐘
3.發(fā)送寫單塊開始字節(jié)0xFE
4.發(fā)送512個字節(jié)數(shù)據(jù)
5.發(fā)送2字節(jié)CRC(可以均為0xff)
6.連續(xù)讀直到讀到XXX00101表示數(shù)據(jù)寫入成功
7.繼續(xù)讀進(jìn)行忙檢測(讀到0x00表示SD卡正忙),當(dāng)讀到0xff表示寫操作完成
寫單塊時序圖:
寫多塊方法:
1.發(fā)送CMD25,收到0x00表示成功
2.發(fā)送若干時鐘
3.發(fā)送寫多塊開始字節(jié)0xFC
4.發(fā)送512字節(jié)數(shù)據(jù)
5.發(fā)送兩個CRC(可以均為0xff)
6.連續(xù)讀直到讀到XXX00101表示數(shù)據(jù)寫入成功
7.繼續(xù)讀進(jìn)行忙檢測,直到讀到0xFF表示寫操作完成
8.如果想讀下一扇區(qū)重復(fù)2-7步驟
9.發(fā)送寫多塊停止字節(jié)0xFD來停止寫操作
10.進(jìn)行忙檢測直到讀到0xFF
上面介紹了Micro SD卡的硬件連接,復(fù)位、初始化、讀寫單塊和多塊的實(shí)現(xiàn)方法,其實(shí)你還可以讀取SD卡ID,給SD卡命名,設(shè)置密碼,改變一次讀寫的大小,這里就不多介紹,大家可以自己看SD卡的官方資料。下一篇文章我就貼出自己寫的基于nios ii的Micro SD卡程序,程序在實(shí)現(xiàn)了上面介紹的功能外,還增加了讀CSD,CID寄存器的功能。
聯(lián)系客服