3、零死角玩轉(zhuǎn)stm32教程.-高級篇_第1頁
3、零死角玩轉(zhuǎn)stm32教程.-高級篇_第2頁
3、零死角玩轉(zhuǎn)stm32教程.-高級篇_第3頁
3、零死角玩轉(zhuǎn)stm32教程.-高級篇_第4頁
3、零死角玩轉(zhuǎn)stm32教程.-高級篇_第5頁
已閱讀5頁,還剩147頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、0、 友情提示零死角玩轉(zhuǎn) STM32系列由初級篇、中級篇、高級篇、系統(tǒng)篇、四個部分組成,根據(jù)野火STM32 開發(fā)板舊版升級而來,且經(jīng)過重新深入編寫,重新排版,更適合初學者,步步為營,從入門到精通,從奔到系統(tǒng),讓您零死角玩轉(zhuǎn)STM32。M3 的世界,于野火,樂意愜無邊。另外,野火團隊歷時一年精心打造的STM32 庫開發(fā)實戰(zhàn)指南將年 10 月份由機械工業(yè),該書的排版更適于紙質(zhì)書本閱讀以及更有利于查閱資料。內(nèi)容上會給你帶來的驚喜。是一本學習STM32 必備的工具書。敬請期待!1、SDIO(4bit + DMA、支持SDHC)1.1 實驗描述及工程文件實驗描述MicroSD 卡(SDIO 模式)測試實

2、驗,采用 4bit 數(shù)據(jù)線模式。沒有跑文件系統(tǒng),只是單純地讀block 并將測試信息通過串口 1 在電腦的超級終端上 打印出來。硬件連接PC12-SDIO-CLK:CLK PC10-SDIO-D2 :DATA2 PC11-SDIO-D3:CD/DATA3 PD2-SDIO-CMD :CMD PC8-SDIO-D0:DATA0PC9-SDIO-D1:DATA1用到的件startup/start_stm32f10 x_hd.c CMSIS/core_cm3.c CMSIS/system_stm32f10 x.c FWlib/stm32f10 x_gpio.c FWlib/stm32f10 x_rc

3、c.c FWlib/stm32f10 x_usart.c FWlib/ stm32f10 x_sdio.c FWlib/ stm32f10 x_dma.c FWlib/ misc.c用戶編寫的文件USER/main.c USER/stm32f10 x_it.c USER/usart1.c USER/ sdio_sdcard.c野火STM32 開發(fā)板 MicroSD 卡硬件原理圖:1.2 SDIO 簡介野火STM32 開發(fā)板的CPU ( STM32F103VET6 )具有一個SDIO 接口。SD/SDIO/MMC 主機接口可以支持MMC 卡系統(tǒng)規(guī)范 4.2 版中的 3 個不同的數(shù)據(jù)總線模式:1

4、位(默認)、4 位和 8 位。在 8 位模式下,該接口可以使數(shù)據(jù)傳輸速率達到 48MHz,該接口兼容SD卡規(guī)范 2.0 版。SDIO卡規(guī)范 2.0 版支持兩種數(shù)據(jù)總線模式:1 位(默認)和 4 位。目前的版本只能一次支持一個SD/SDIO/MMC 4.2 版的卡,但可以同時支持多個MMC 4.1 版或之前版本的卡。除了SD/SDIO/MMC,這個接口完全與 CE-ATA 數(shù)字協(xié)議版本 1.1 兼容。1.3 SD 協(xié)議大多數(shù)人原來沒有了解過SD 協(xié)議,又看到SDIO 的驅(qū)動有 2000 多行,感覺無從下手。所以野火重新寫了這個文檔進行詳細的解釋,幫助大家更快地跨過這道檻。附資料:Simplifi

5、ed_Physical_Layer_Spec.pdf,這個資料包含了SDIO協(xié)議中SD卡的部分。下面野火結(jié)合STM32 的SDIO,分析SD 協(xié)議,讓大家對它先有個大概了解,更具體的說明在代碼中展開。SDIO 接口圖一從SDIO 的時鐘說起。SDIO_CK 時鐘是通過PC12 引腳連接到SD 卡的,是SDIO 接口與SD 卡用于同步的時鐘。SDIO 選配器掛載到AHB 總線上,通過HCLK 二分頻輸入到適配器得到 SDIO_CK 的時鐘,這時SDIO_CK = HCLK/(2+CLKDIV)。其中CLKDIV 是 SDIO_CLK(寄存器)中的CLKDIV 位。另外,SDIO_CK 也可以由S

6、DIOCLK 通過設(shè)置 bypass 模式直接得到,這時SDIO_CK = SDIOCLK=HCLK。通過下面的庫函數(shù)來配置時鐘:1. SDIO_Init(&SDIO_InitStructure);對SD 卡的操作一般是大吞吐量的數(shù)據(jù)傳輸,所以采用 DMA 來提高效率,SDIO 采用的是DMA2 中的通道 4。在數(shù)據(jù)傳輸?shù)臅r候SDIO 可向DMA 發(fā)出請求。二講解SDIO令、數(shù)據(jù)傳輸方式。SDIO 的所有命令及命令響應(yīng),都是通過SDIO-CMD 引腳來傳輸?shù)摹C钪荒苡蒱ost 即STM32 的SDIO 控制器發(fā)出。SDIO 協(xié)議把命令分成了11 種,包括基本命令,讀寫命令還有ACMD 系列命

7、令等。其中,在發(fā)送ACMD命令前,要先向卡發(fā)送為CMD55令。參照下面令格式圖,其中的start bit,transmisbit ,crc7,上配置的時候只需要endbit,都是由STM32 中的SDIO 硬件完成,在d index 和命令參數(shù)mand index 就是命令索引設(shè)置。(),如CMD0,CMD1被成 0,1.。有令會包含參數(shù),讀命令的地址參數(shù)等,這個參數(shù)被存放在argument 段。SD 卡命令格式可以通過下面的函數(shù)來配置、發(fā)送命令:1.mand(&SDIO_CmdInitStructure);/發(fā)送命令SD 卡對host 的各種命令的回復稱為響應(yīng),除了CMD0 命令外,SD 卡

8、在接收到命令都會返回一個響應(yīng)。對于不同令,會有不同的響應(yīng)格式,共 7種,分為長響應(yīng)型(136bit)和短響應(yīng)型(48bit)。以下圖,響應(yīng) 6(R6)為例:SD 卡命令響應(yīng)格式(R6)SDIO 通過CMD 接收到響應(yīng)后,硬件去除頭尾的信息,把保存到SDIO_RESPCMD 寄存器,把argument field 內(nèi)容保存d index到SDIO_RESPx 寄存器中。這兩個值可以分別通過下面的庫函數(shù)得到。1.mandResponse(); /卡返回接收到令2. SDIO_GetResponse(SDIO_RESP1); /卡返回的 argument field 內(nèi)容數(shù)據(jù)寫入,。請看下面的寫數(shù)據(jù)

9、時序圖,在上,要處理的的實驗中用的是Micro SD 卡,有 4 條數(shù)據(jù)線,默認的時只是讀忙。另外,候SDIO 采用 1 條數(shù)據(jù)線的傳輸方式,更改為 4 條數(shù)據(jù)線模式要通過向卡發(fā)送命令來更改。SD 卡的多塊寫入時序圖三卡的種類。STM32 的SDIO 支持SD其中SDI/O 卡與SD卡,SD I/O 卡 ,MMC 卡??ㄊ怯袇^(qū)別的,SDI/O 卡實際上就是利用SDIO 接口SD 的插槽中,擴展設(shè)備的功能,如:SDI/O wifi, SDI/O的一些模塊,cmos 相機等。而SD卡就是平時常見的單純用于數(shù)據(jù)的卡??墒褂?SDIO 接口類型的卡本實驗中使用的Micro SD 卡屬于SDSC(標準容

10、量,最大兩 G)卡。介紹卡的種類是因為SD 協(xié)議中令也支持這三種類型的卡,因此對STM32 中的SDIO 接口進行初始化后,上電后就要對接入的卡進行檢測、分類,這個過程是通過向卡發(fā)送一系列不同令,根據(jù)卡不同的響應(yīng)來進行分類。下面進入代碼展開具體講解。1.4 代碼分析首先要添加用的件,在工程文件夾下Fwlib 下需添加以下件:FWlib/stm32f10 x_gpio.cFWlib/stm32f10 x_rcc.cFWlib/stm32f10 x_usart.cFWlib/stm32f10 x_sdio.cFWlib/stm32f10 x_dma.cFWlib/misc.c還要在 stm32f1

11、0 x_conf.h 中把相應(yīng)的頭文件添加進來:#include stm32f10 x_dma.h#include stm32f10 x gpio.h#include stm32f10 x rcc.h#include stm32f10 x sdio.h#include stm32f10 x usart.h#include misc.h保持良好的,從main 函數(shù)開始分析:1.2.3.4.main(void)/*進入到 main 函數(shù)前,啟動文件startup(startup_stm32f10 x_xx.s)已經(jīng)調(diào)用了在5.system_stm32f10 x.c 中的SystemInit(),配

12、置好了系統(tǒng)時鐘,在外部晶振 8M的條件下,設(shè)置HCLK = 72M */6.7.8.9.10.11.12.13.14./*errupt Config */NVIC_Configuration();/* USART1 config */ USART1_Config();/*SD Init*/15.16.17.Sus = SD Init();prf( rn 這是一個MicroSD 卡實驗(沒有跑文件系統(tǒng))rn );18.19.20.21.22.23.24.25.26.27.28.29.30.31.if(Sus= SD_OK) /檢測初始化是否成功f( rn SD_Init 初始化成功 rn );p

13、relsepr prf(rn SD_Init 初始化失敗 rn );f(rn 返回的Sus 的值為: %d rn,Sus );pr prf(f(rnrnCardType is :%d , SDCardInfo.CardType ); CardCapacity is :%d , SDCardInfo.CardCapacity );32.prf(rnCardBlockSize is :%d , SDCardInfo.CardBlockSize );33.34.pr prf(f();rnrnRCA is :%d , SDCardInfo.RCA);ManufacturerID is :%d rn,

14、SDCardInfo.SD_cid.ManufacturerID35.36.37.38.39.40.41.42.43.SD_EraseTest();/擦除測試SD_SinglockTest(); /單塊讀寫測試SD_MultiBlockTest(); /多塊讀寫測試while (1)44. main 函數(shù)的流程簡單明了:1.2.用NVIC_Configuration()初始化好SDIO 的中斷;用USART1_Config()配置好用于返回調(diào)試信息的串口,SD_Init()開始進行SDIO 的初始化;3.最后分別用SD_EraseTest()、SD_SinglockTest()、SD_Mult

15、iBlockTest()進行擦除,單數(shù)據(jù)塊讀寫,多數(shù)據(jù)塊讀寫測試。下面先進入SDIO 驅(qū)動函數(shù)的大頭SD_Init()進行分析:1.2.3.4.5.6.7.8.9./*函數(shù)名:SD_Init描述輸入輸出:初始化SD 卡,使卡處于就緒狀態(tài)(準備傳輸數(shù)據(jù)):無:-SD_Error SD 卡錯誤代碼成功時則為 SD_OK:外部調(diào)用調(diào)用*/SD_Error SD_Init(void)10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37.

16、 38. 39. 40.41.42.43./*重置 SD_Error 狀態(tài)*/ SD_Error errorsus = SD_OK;/* SDIO 外設(shè)底層引腳初始化 */ GPIO_Configuration();/*對 SDIO 的所有寄存器進行復位*/ SDIO_DeInit();/*上電并進行卡識別流程,確認卡的操作電壓 */errorsus = SD_erON();/*如果上電,識別不成功,返回“響應(yīng)超時”錯誤 */if (errorsus != SD_OK)/*! CMD Response TimeOut (wait for CMDSENTreturn(errorsus);flag

17、) */*卡識別成功,進行卡初始化*/errorsus = SD_InitializeCards();if (errorsus != SD_OK)/失敗返回/*! CMD Response TimeOut (wait for CMDSENTreturn(errorsus);flag) */*! Configure the SDIO peripheral上電識別,卡初始化都完成后,進入數(shù)據(jù)傳輸模式,提高讀寫速度速度若超過 24M 要進入bypass 模式! on STM32F2xx devi, SDIOCLK is fixed to 48MHz! SDIOCLK = HCLK, SDIO_CK

18、= HCLK/(2 + SDIO_TRANSFER_CLK_DIV)*/44.45.SDIO InitStructure.SDIO ClockDiv = SDIO TRANSFER CLK DIV; SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;/上升沿數(shù)據(jù)SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable; /時鐘頻率若超過 24M,要開啟此模式46.47.SDIO_InitStructure.SDIO_ClockerSave = SDIO_Cloc

19、kerSave_Disable;/若開啟此功能,在總線空閑時關(guān)閉 sd_clk 時鐘 SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;/1 位模式SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_ Disable; /硬件流,若開啟,在FIFO 不能進行發(fā)送和接收數(shù)據(jù)時,數(shù)據(jù)傳輸暫停SDIO_Init(&SDIO_InitStructure);48.49.50.51.52.53.54.if (errorsus = SD_OK)/*ReaD/CID MS

20、D registers */55.errorsus =SD_GetCardInfo(&SDCardInfo);/用來csd/cid 寄存器56.57.58.59.60.if (errorsus= SD_OK)/*Select Card*/61.errorsus =SD_SelectDeselect(u32_t) (SDCardInfo.RCA 16);/通過cmd7,rca 選擇要操作的卡62.63.64.65.66.if (errorsus= SD_OK)errors 4bits 模式us =SD_EnableWideBusOperation(SDIO_BusWide_4b);/開啟67.6

21、8.69.return(errorsus);70. 先從整體上了解這個SD_Init()函數(shù):1.用 GPIO Configuration()進行SDIO 的端口底層配置2.分別調(diào)用了 SD erON()和SD InitializeCards()函數(shù),這兩個函數(shù)共同實現(xiàn)了上面提到的卡檢測、識別流程。調(diào)用 SDIO Init(&SDIO InitStructure)庫函數(shù)配置SDIO 的時鐘,數(shù)據(jù)線寬度,硬件流(在讀寫數(shù)據(jù)的時候,開啟硬件流是和很必要的,可以減少出錯)調(diào)用SD_GetCardInfo(&SDCardInfo)獲取 sd 卡的CSD 寄存器中的內(nèi)容,在main 函數(shù)里輸出到串口的數(shù)

22、據(jù)就是這個時候從卡得到的。調(diào)用SD_SelectDeselect()選定后面即將要操作的卡。調(diào)用 SD EnableWideBusOperation(SDIO BusWide 4b)開啟 4bit 數(shù)據(jù)線模式如果SD_Init()函數(shù)能夠執(zhí)行完整個流程,并且返回值是SD_OK 的話則說明初始化成功,就可以開始進行擦除、讀寫的操作了。下面進入SD_erON()函數(shù),分析完這個函數(shù)大家就能了解SDIO 如何接收、發(fā)送命令了。1.2.3.4.5.6.7.8.9./*函數(shù)名:SD_erON描述輸入輸出:確保SD 卡的工作電壓和配置控制時鐘:無:-SD_Error SD 卡錯誤代碼成功時則為 SD_OK

23、:在 SD_Init() 調(diào)用*調(diào)用*/SD_Error SD_erON(void)10. 11. 12. 13. 14. 15.SD_Error errorsus = SD_OK;u32_t response = 0, count = 0, validvoltage = 0; u32_t SDType = SD_STD_CAPACITY;/*!er ON Sequence*/16.17.18.19.20.21./*! Configure the SDIO peripheral */*! SDIOCLK = HCLK, SDIO_CK = HCLK/(2 + SDIO_INIT_CLK_DIV

24、) */*! on STM32F2xx devi, SDIOCLK is fixed to 48MHz */*! SDIO_CK for initialization should not exceed 400 KHz */*初始化時的時鐘不能大于 400KHz*/SDIO_InitStructure.SDIO_ClockDiv = SDIO_INIT_CLK_DIV; /* HCLK = 72MHz, SDIOCLK = 72MHz, SDIO_CK = HCLK/(178 + 2) = 400 KHz */SDIO_InitStructure.SDIO_ClockEdge = SDIO_C

25、lockEdge_Rising;SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable; /不使用bypass 模式,直接用HCLK 進行分頻得到SDIO_CK22.23.24.SDIO_InitStructure.SDIO_ClockerSave = SDIO_Clock/ 空閑時不關(guān)閉時鐘電源SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;/1 位數(shù)據(jù)線erSave_Disable; /25./26.SDIO_InitStructure.SDIO_HardwareFlo

26、wControl = SDIO_HardwareFlowControl_Disable;/硬件流27.28.29.30.31.32.33.34.35.36.SDIO_Init(&SDIO_InitStructure);/*! Set SDIO_Seter S erSe to ON */ e(SDIO_erSe_ON);/*! Enable SDIOClock */SDIO_ClockCmd(ENABLE);/*下面發(fā)送一系列命令,開始卡識別流程*/*! CMD0: GO_IDLE_SE*/37.38.39.40.41.42./*! No CMD response required */ SDI

27、O_CmdInitStructure.SDIO_Argument = 0 x0; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_GO_IDLE_SE; /cmd0 SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_No; /無響應(yīng) SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; /則 CPSM 在開始發(fā)送命令之前等待數(shù)據(jù)傳輸結(jié)束。/寫命令進命令寄存器

28、43.44.45.46.47.48.49.50.51.52.53.mand(&SDIO_CmdInitStructure);errorsus = CmdError();/檢測是否正確接收到cmd0if (errorsus != SD_OK) /命令發(fā)送出錯,返回/*! CMD Response TimeOut (waitreturn(errorsus);for CMDSENT flag) */*! CMD8: SEND_IF_COND*/54.55.56./*! Send CMD8 to verify SD card/*! Argument: - 31:12:erface operating

29、condition */ (shall be set to 0)- 11:8: Supply Voltage (VHS) 0 x1 (Range: 2.7-3.6 V)57.58.59.- 7:0: Check Pattern/*! CMD Response: R7 */ SDIO_CmdInitStructure.SDIO_Argument會返回這個參數(shù)SDIO_CmdInitStructure.SDIO_CmdIndex SDIO_CmdInitStructure.SDIO_Response(mended 0 xAA) */=SD_CHECK_PATTERN;/接收到命令 sd60.61.

30、62.=SDIO_SEND_IF_COND; /cmd8SDIO_Response_Short;/r7SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;/關(guān)閉等待中斷63.64.65.66.67.68.69.70.71.SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; mand(&SDIO_CmdInitStructure);/*檢查是否接收到命令*/errorsus = CmdResp7Error();if (errorsus = SD_OK)/有響應(yīng)則 card 遵循 sd 協(xié)議 2.0 版本

31、CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0; /*! SD Card 2.0 ,先把它定義會sdsc 類型的卡*/SDType = SD_HIGH_CAPACITY; /這個變量用作 acmd41 的參數(shù),用來詢問是sdsc 卡還是sdhc 卡else /無響應(yīng),說明是 1.x 的或mmc 的卡/*! CMD55 */ SDIO_CmdInitStructure.SDIO_Argument = 0 x00;SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; SDIO_CmdInitStructure

32、.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;mand(&SDIO_CmdInitStructure); errorsus = CmdResp1Error(SD_CMD_APP_CMD);72.73.74.75.76.77.78.79.80.81.82.83.84.85.86.87.88.89.90.91.92.93./*! CMD55 */為什么在 else 里和el

33、se 外面都要發(fā)送CMD55?/發(fā)送 cmd55,用于檢測是 sd 卡還是mmc 卡,或是不支持的卡 SDIO_CmdInitStructure.SDIO_Argument = 0 x00; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; /r1 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_

34、CPSM_Enable;mand(&SDIO_CmdInitStructure);errorsus = CmdResp1Error(SD_CMD_APP_CMD);不支持的卡/是否響應(yīng),沒響應(yīng)的是mmc 或94.95.96./*! If errors/*! If errorsus isd TimeOut, it isa MMC card */SD card 2.0 (voltage rangus is SD_OK it is a SD card:emismatch)97.98.99.or SD card 1.x */us = SD_OK) /響應(yīng)了 cmd55,是 sd 卡,可能為 1.x,可

35、能為 2.0if(errors/*下面開始循環(huán)地發(fā)送 sdio 支持的電壓范圍,循環(huán)一定次數(shù)*/100.101.102.103.104.105.106.CMD55 107.108.109./*! SD CARD */*! Send ACMD41 SD_APP_OP_COND wirgument 0 x80100000 */while (!validvoltage) & (count SD_MAX_VOLT_TRIAL)/因為下面要用到 ACMD41,是ACMD 命令,在發(fā)送ACMD 命令前都要先向卡發(fā)送/*! 31) = 1) ?寄存器的pwr_up 位,看是否已工作在正常電壓137.138.

36、139.140.141.壓142.143.144.145.count+;/計算循環(huán)次數(shù)if (count = SD_MAX_VOLT_TRIAL) /循環(huán)檢測超過一定次數(shù)還沒上電errorsus = SD_INVALID_VOLTRANGE;/SDIO 不支持card 的供電電return(errorsus);/*檢查卡返回信息中的HCS 位*/if (response&= SD_HIGH_CAPACITY) /判斷ocr 中的ccs 位 ,如果是sdsc卡則不執(zhí)行下面的語句146.147.SDIO_HIGH_CAPACITY_SD_CARD; /把卡類型從初始化的sdsc 型CardType

37、 =改為sdhc 型148.149.150.151.152.153./*! else MMCCard */return(errorsus);這個函數(shù)的流程就是卡的上電、識別操作,如下圖:卡的上電,識別流程:截圖來自Simplified_Physical_Layer_Spec.pdf page27代碼中所有的判斷語句都是根據(jù)這個圖的各個識別展開的,最終把卡分為 1.0 版的SD卡,2.0 版的SDSC 卡和 2.0 版的SDHC 卡。在這個代碼流程中有兩點要注意一下:1.初始化的時鐘。SDIO_CK 的時鐘分為兩個階段,在初始化階段SDIO_CK的頻率要小于 400KHz,初始化完成后可把SDI

38、O_CK 調(diào)整成高速模式,高速模式時超過 24M 要開啟bypass 模式,對于SD卡即使開啟bypass,最高頻過 25MHz。 2.CMD8 命令。CMD8 命令格式。率CMD8 命令中的VHS 是用來確認主機SDIO 是否支持卡的工作電壓的。Check pattern 部分可以是任何數(shù)值,若SDIO 支持卡的工作電壓,卡會把接收到的 check pattern 數(shù)值原樣返回給主機。CMD8 命令的響應(yīng)格式 R7:在驅(qū)動程序中調(diào)用了CmdResp7Error()來檢驗卡接收命令后的響應(yīng)。 3.ACMD41 命令。這個命令也是用來進一步檢查SDIO 是否支持卡的工作電壓的,協(xié)議要它在調(diào)用它之

39、前必須先調(diào)用CMD8,另外還可以通過它命令參數(shù)中的HCS 位來區(qū)分卡是SDHC 卡還是SDSC 卡。確認工作電壓時循環(huán)地發(fā)送ACMD41,發(fā)送后檢查在SD 卡上的OCR 寄存器中的pwr_up 位,若pwr_up 位置為 1,表明SDIO 支持卡的工作電壓,卡開始正常工作。同時把ACMD41 中令參數(shù)HCS 位置 1,卡正常工作的時候檢測OCR 寄存器中的 CCS 位,若 CCS 位為 1 則說明該卡為SDHC 卡,為零則為SDSC 卡。因為ACMD41 命令屬于ACMD 命令,在發(fā)送ACMD 命令前都要先發(fā)送CMD55.ACMD41 命令格式ACMD41 命令的響應(yīng)(R3),返回的是 OCR

40、 寄存器的值OCR 寄存器的內(nèi)容SD 卡上電確認成功后,進入SD_InitializeCards()函數(shù):1.2.3.4.5.6.7./*函數(shù)名:SD_InitializeCards描述輸入輸出:初始化所有的卡或者單個卡進入就緒狀態(tài):無:-SD_Error SD 卡錯誤代碼成功時則為 SD_OK:在 SD_Init() 調(diào)用,在調(diào)用er_on()上電卡識別完畢后,調(diào)用此函數(shù)進調(diào)用行卡初始化*/SD_Error SD_InitializeCards(void)8.9.10. 11. 12. 13. 14. 15. 16. 17. 18. 19.20.21.22.23.24.25.26.27.28

41、.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.SD_Error errorsus = SD_OK;u16_t rca = 0 x01;if (SDIO_GeterSe() = SDIO_erSe_OFF)errorsus = SD_REQUEST_NOT_APPLICABLE;return(errorsus);if (SDIO_SECURE_DIGITAL_IO_CARD != CardType)/判斷卡的類型/*! Send CMD2 ALL_SEND_CID */ SDIO_CmdInitStructure.SDIO_Argument =

42、 0 x0; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ALL_SEND_CID; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;mand(&SDIO_CmdInitStructure);errorsus = CmdResp2Error();if (SD_OK != errorsus

43、)return(errorsus);CID_Tab0 = SDIO_GetResponse(SDIO_RESP1); CID_Tab1 = SDIO_GetResponse(SDIO_RESP2); CID_Tab2 = SDIO_GetResponse(SDIO_RESP3); CID_Tab3 = SDIO_GetResponse(SDIO_RESP4);/*下面開始SD 卡初始化流程*/if (SDIO_STD_CAPACITY_SD_CARD_V1_1 = CardType) | (SDIO_STD_CAPACITY_SD_CARD_V2_0 = CardType) | (SDIO_S

44、EC= CardType)BO_CARD =45.| (SDIO_HIGH_CAPACITY_SD_CARD = CardType) /使用的是 2.0 的卡46.47.48.49.50./*! Send CMD3 SET_REL_ADDR wirgument 0 */*! SD Card publishes its RCA. */ SDIO_CmdInitStructure.SDIO_Argument = 0 x00; SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_REL_ADDR; /cmd351.52.53.54.55.56.SDIO_

45、CmdInitStructure.SDIO_Response = SDIO_Response_Short; /r6 SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;mand(&SDIO_CmdInitStructure);errorsus = CmdResp6Error(SD_CMD_SET_REL_ADDR, &rca); /把接收到的卡相對地址存起來。57.58.59.60.if (SD_OK != errorsus)return(error

46、sus);61.62.63.64.65.66.67.68.69.70.71.72.73.74.75.76.77.78.79.80.81.82.83.84.85.86.87.88.89.90.91.92. if (SDIO_SECURE_DIGITAL_IO_CARD != CardType)RCA = rca;/*! Send CMD9 SEND_CSD wirgument as cards RCA */SDIO_CmdInitStructure.SDIO_Argument = (u32_t)(rca 16); SDIO_CmdInitStructure.SDIO_CmdIndex = SD_

47、CMD_SEND_CSD; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;mand(&SDIO_CmdInitStructure);errorsus = CmdResp2Error();if (SD_OK != errorsus)return(errorsus);CSD_Tab0 = SDIO_GetResponse(SDIO_R

48、ESP1); CSD_Tab1 = SDIO_GetResponse(SDIO_RESP2); CSD Tab2 = SDIO GetResponse(SDIO RESP3);CSD_Tab3 = SDIO_GetResponse(SDIO_RESP4);errorsus = SD_OK; /*!DCTRL =0 x0;if (CardType = SDIO_HIGH_CAPACITY_SD_CARD)BlockSize = 512;WriteAddr /= 512;/*add,沒有這一段容易卡死在DMA 檢測中*/33./*! Set Block Size for Card,cmd16,若是

49、sdsc 卡,可以用來設(shè)置塊大小,若是sdhc 卡,塊大512 字節(jié),不受cmd16 影響 */34.35.36.37.38.39.40.41.42.43.44.45.46.47.SDIO_CmdInitStructure.SDIO_Argument = (u32_t) BlockSize;SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SD

50、IO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;mand(&SDIO_CmdInitStructure);/r1errorsus = CmdResp1Error(SD_CMD_SET_BLOCKLEN);if (SD_OK != errorsus)return(errorsus);/*/48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64./*! To improve performance */ SDIO_CmdInitStructure.SDIO_Argument

51、= (u32_t) (RCA 16); SDIO CmdInitStructure.SDIO CmdIndex = SD CMD APP CMD; / cmd55 SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;mand(&SDIO_CmdInitStructure);errorsus = CmdResp1Error(SD_CMD

52、_APP_CMD);if (errorsus!= SD_OK)return(errorsus);/*! To improve行預(yù)擦除performance */ pre-erased,在多塊寫入時可發(fā)送此命令進65.SDIO_CmdInitStructure.SDIO_Argument參數(shù)為將要寫入的塊數(shù)目SDIO_CmdInitStructure.SDIO_CmdIndex23SDIO_CmdInitStructure.SDIO_Response=(u32_t)NumberOfBlocks; /66.=SD_CMD_SET_BLOCK_COUNT; /cmd67.68.69.70.71.=S

53、DIO_Response_Short;SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; mand(&SDIO_CmdInitStructure);72.73.74.75.76.77.78.79.80.81.82.83.84.85.86.87.88.89.90.91.92.93.94.95.96.errorsus = CmdResp1Error(SD_CMD_SET_BLOCK_COUNT);if (errorsus!= SD_OK)return(e

54、rrorsus);/*! Send CMD25WRITE_MULT_BLOCK wirgument data address */SDIO_CmdInitStructure.SDIO_Argument = (u32_t)WriteAddr;SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_MULT_BLOCK; SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; SDIO_CmdIn

55、itStructure.SDIO_CPSM = SDIO_CPSM_Enable;SDIOmand(&SDIO CmdInitStructure);errorsus = CmdResp1Error(SD_CMD_WRITE_MULT_BLOCK);if (SD_OK != errorsus)return(errorsus);SDIO_DataInitStructure.SDIO_DaimeOut = SD_DAIMEOUT;SDIO DataInitStructure.SDIO DataLength = NumberOfBlocks * BlockSize;97.98.SDIO_DataIni

56、tStructure.SDIO_DataBlockSize = (u32_t) 9 diskio.c - ff.c 。關(guān)于具體源碼的分析不是我能力所及呀,大家就自己吧。主要工作是帶領(lǐng)大家把這個文件系統(tǒng)移植到的開發(fā)板上,讓這個文件系統(tǒng)先跑起來,這樣才是硬道理呀。文件系統(tǒng)工作起來了的話,源碼的分析那自然是大家的活啦。2.5 開始移植首先要獲取一個完全沒有修改過的文件系統(tǒng)源碼,然后在 10-MicroSD卡這個文件夾下的實驗代碼下移植,這個實驗代碼實現(xiàn)的是卡的底層的塊操作。注意,在移植這個文件系統(tǒng)的過程中會盡量保持文件系統(tǒng)源碼的純凈,盡量做到在修改最少量的源碼的情況下移植成功。首先將eger.h、d

57、iskio.h、diskio.c、ff.h、ff.c 添加到工程目錄下的USER 文件夾下,如下截圖:然后并回到MDK 界面下將diskio.c 、ff.c 這兩個文件添加到USER 目錄下,如下截圖:因為要用到這兩個c 文件,所以在main.c 中將這兩個c 文件對應(yīng)的頭文件diskio.h 、ff.h 包含進來,如下截圖:好嘞,下面開始編譯,這時會出現(xiàn)如下錯誤:意思是說 FALSE 跟 TRUE 這兩個變量已經(jīng)定義過了,為什么會出現(xiàn)這個錯誤呢?因為在eger.h 和的M3 庫頭文件stm32f10 x.h 中都定義了這兩個變量,所以就產(chǎn)生了重復定義:eger.hstm32f10 x.h怎么

58、解決呢,很簡單,只要搞掉一個即可,但要去掉哪個呢?外面的M3 庫很多文件都包含了stm32f10 x.h 這個頭文件,假如是修改考慮到stm32f10 x.h 的話工作量會非常大,鑒于此就只能委屈下,將它注釋掉:eger.h 了,修改如好嘞,修改之后,再編譯下,接著又出現(xiàn)如下錯誤:意思是說在diskio.h、ff.c 中 BOOL 、FALSE、TRUE 沒定義。剛剛才把人家注釋掉了,不報錯才怪。解決方法如下:1、將eger.h 中有關(guān)BOOL 的那句注釋掉,注釋掉也沒太大關(guān)系,因為注釋掉的不會怎么用到:2、在ff.c 文件的開頭重新定義一個stm32f10 x.h 中的名字一樣:變量,取名為

59、 bool,與同時在 ff.c 的第 585 行做如下修改:現(xiàn)在再編譯下,發(fā)現(xiàn)既沒警告也沒錯誤:到這里算是把文件系統(tǒng)移植成功了,接下來的任務(wù)就是調(diào)用文件系統(tǒng)的函數(shù)來操作的卡了。其實這里的移植是非常非常簡單的,要是你學過LINUX 的話,那里面的UBOOT 移植,系統(tǒng)移植,那才叫人頭疼,就光是目錄里面的文件夾都幾千個,更別說是找到要修改的源代碼了,剛接觸的話絕對叫你吐血,就連個交叉編譯器都涉及到移植。2.6 實驗代碼分析FATFS 是獨立于底層介質(zhì)的應(yīng)用函數(shù)庫,對底層介質(zhì)的操作都要交給用戶去實現(xiàn),其僅僅是提供了一個函數(shù)接口而已,函數(shù)為空,要用戶添加代碼。這幾個函數(shù)的原型如下,在diskio.c

60、中定義:1./* Inidialize a Drive */2.DSUS disk_initialize (3.BYTE drv/* Physical drive nmuber (0.) */4.)1./* Return Disk Sus */2.DSUS disk_sus (3.BYTE drv/* Physical drive nmuber (0.) */4.)1./* Read Sector(s) */2.DRESUisk_read (3.BYTE drv,/* Physical drive nmuber (0.) */4.BYTE *buff, /* Data buffer to st

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論