STM32學(xué)習(xí)筆記——SDIO(1)
這個圖看起來有點復(fù)雜,感覺無從下手,其實仔細(xì)瞧瞧就跟我們數(shù)電學(xué)的狀態(tài)轉(zhuǎn)移圖差不多,框框里面是各種操作,箭頭指向下一步操作,直線引出去的部分就是狀態(tài)發(fā)生跳轉(zhuǎn)的條件。首先上電(power-on),然后發(fā)出CMD0,再接著發(fā)送CMD8,有應(yīng)答(response)判斷為Ver2.00或更新的SDMC,無應(yīng)答(no response)判斷為ver2.00或者更新版SDMC(電壓不匹配(voltage mismatch) )或ver1.X SDMC或不是SDMC。若判斷為前一種情況,則問詢是否為有效應(yīng)答(valid response),如果不是,判斷為無效卡,否則判斷為有效卡且開始循環(huán)發(fā)送ACMD41指令直至SD卡發(fā)出power up應(yīng)答。然后判斷CCS(card capacity status——卡容量狀態(tài))位,為1則判斷為ver2.00或者更新的大容量卡(high capacity SD memory card),否則判斷為ver2.00或者更新的標(biāo)準(zhǔn)卡(sandard capacity SD memory card)。至此,power on工作結(jié)束。
上文只是對狀態(tài)圖進行了一個解讀,真正要控制還是需要知道各個CMD如何發(fā)送。SD卡協(xié)議提供了幾個CMD的格式以及其響應(yīng)值的格式(如果有相應(yīng)的話)。下面就對函數(shù)的具體編寫進行下總結(jié)。
(1)初始化SDIO
利用SDIO_Init中的結(jié)構(gòu)體初始化SDIO接口。該結(jié)構(gòu)體有以下幾個成員函數(shù):SDIO_ClockDiv、SDIO_ClockEdge、SDIO_ClockBypass、SDIO_ClockPowerSave、SDIO_BusWide、SDIO_HardwareFlowControl。其中比較重要的是SDIO_ClockDiv成員,它確定了SDIO的分頻系數(shù),在不使用旁路時鐘(ByPass)的時候SDIO_CLK=HCLK/(SDIO_ClockDiv+2),我們在這里將SDIO_CLK設(shè)置為400kHZ,就是通過設(shè)置分頻系數(shù)實現(xiàn)的。初始化完成后,就進行第一步,也就是power on,調(diào)用SDIO_SetPowerState函數(shù)即可。最后別忘記使能SDIO的時鐘。
(2)發(fā)送CMD0
由STM32向SD卡發(fā)送指令可以直接調(diào)用SDIO_SendCommand函數(shù),該函數(shù)包含一個結(jié)構(gòu)體,該結(jié)構(gòu)體有以下幾個成員:SDIO_Argument、SDIO_CmdIndex、SDIO_Response、SDIO_Wait、SDIO_CPSM。跟我們編程密切相關(guān)的一個是SDIO_Argument——參數(shù),許多帶有響應(yīng)的命令都需要通過設(shè)置參數(shù)來實現(xiàn),由于CMD0沒有響應(yīng),所以此處設(shè)為0x00即可。SDIO_CmdIndex成員是該結(jié)構(gòu)體核心——指令指數(shù)。也就是說,如果我要發(fā)送CMD0,SDIO_CmdIndex=0,如果發(fā)送ACMD41,SDIO_CmdIndex=41,但是注意此處SDIO_CmdIndex的值是等于指令,而且是指令的十進制形式,但是我們在給SDIO_CmdIndex賦值時必須轉(zhuǎn)換成十六進制。SDIO_Wait設(shè)置等待中斷。填寫好結(jié)構(gòu)體后檢測是否正確受到CMD0,然后才能進行下一步。為了保證程序正確,這樣的檢測在每一個指令發(fā)送周期都是必須的。
(3)發(fā)送CMD8
用同樣類似的方式發(fā)送CMD8。注意此時CMD8是帶有響應(yīng)的指令,接收到指令后sd返回該SDIO_Argument的值,所以對SDIO_Argument要進行特殊設(shè)置,設(shè)置后SDIO->ARG寄存器便有了該值。SDIO_Response——把應(yīng)答模式設(shè)置成短應(yīng)答,這是根據(jù)參考指南設(shè)置的。同樣地,在填寫完結(jié)構(gòu)體后檢查是否接收到命令。根據(jù)SD協(xié)議初始化流程圖,此時如果有響應(yīng)則SD遵循2.00協(xié)議,否則說明是1.x 或者mmc。無論是哪一種情況,都發(fā)送CMD55來檢測。
(4)發(fā)送CMD55
CMD55是一個特殊的指令,該指令告訴主機下一個command將會是一個應(yīng)用指令(application command),比如要發(fā)送ACMD41之前必須先發(fā)送CMD55。此處發(fā)送CMD55是為了檢測卡的類型。不過暫時沒沒看懂為什么是發(fā)送CMD55,因為關(guān)于CMD55的解釋中并沒有提到它能夠檢測卡類型,只說了它的應(yīng)答類型是R1。判斷是SD卡或者是不支持的卡。
(5)進入循環(huán),再次發(fā)送CMD55
這次發(fā)送CMD55就是為發(fā)送ACMD41做準(zhǔn)備了。為什么要在循環(huán)里發(fā)送呢?因為SD協(xié)議初始化狀態(tài)圖中發(fā)送ACMD的過程是一個反復(fù)地,指導(dǎo)檢測出power up為1為止,所以該處的循環(huán)條件設(shè)置成!validvoltage,validvoltage為OCR的power up位。需要注意的是例程中的循環(huán)條件是(!validvoltage) && (count < SD_MAX_VOLT_TRIAL),也就是說它設(shè)置了一個最大檢測次數(shù),當(dāng)超過該檢測次數(shù)仍然沒有power up時就可以跳出,反饋檢測失敗的信息,這樣程序不會死在此處。
(6)發(fā)送ACMD41
發(fā)送了CMD55后檢測到收到指令,緊接著發(fā)送ACMD41指令。ACMD41響應(yīng)類型是R3,該響應(yīng)返回OCR寄存器的值,稍后我們需要這個寄存器來判斷卡容量以及power up狀態(tài)。注意此處參數(shù)格式規(guī)定的是HCS和Voltage Window共同確定的。填寫完結(jié)構(gòu)體后檢查是否正確接收指令,然后檢測power up位是不是1,不是的話再次循環(huán),是則根據(jù)條件跳出循環(huán)。如果達(dá)到最大循環(huán)次數(shù)power up仍然沒置位,則返回卡不可用的信息。
(7)檢測卡的最終類型
正常上電好后,檢測OCR的CCS為,一次來判斷卡是SDHC還是SDSC。至此,power on函數(shù)功能到此結(jié)束。
評論