<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STM32學(xué)習(xí)筆記——SDIO(1)

          STM32學(xué)習(xí)筆記——SDIO(1)

          作者: 時(shí)間:2016-11-21 來源:網(wǎng)絡(luò) 收藏
          STM32SDIO——SD卡輸入/輸出模塊摸索了一下,今天只看了POWER UP這個(gè)函數(shù)的實(shí)現(xiàn)。對SDIO編寫驅(qū)動,需要參考SD卡的協(xié)議,我手上的SD卡協(xié)議是ver2.00的物理層簡化協(xié)議。協(xié)議主要規(guī)定了主機(jī)(這里就是STM32)向SD卡寫入的各種控制指令,以及SD卡的初始化過程狀態(tài)轉(zhuǎn)移圖。了解SD卡從初始化狀態(tài)轉(zhuǎn)移圖開始。


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


          關(guān)鍵詞: STM32學(xué)習(xí)筆記SDI

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();