當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]今天要給大家分享的是使用FatFs這個庫來讀寫SD卡上面的文件。工程的初始化函數(shù)和FatFs都是通過STM32CubeMX配置生成的,不需要我們手動添加庫。今天分享的內(nèi)容和我的上一篇帖子SDIO讀取SD卡的扇區(qū)有關(guān),最好掌握了SDI

 

今天要給大家分享的是使用FatFs這個庫來讀寫SD卡上面的文件。工程的初始化函數(shù)和FatFs都是通過STM32CubeMX配置生成的,不需要我們手動添加庫。
今天分享的內(nèi)容和我的上一篇帖子SDIO讀取SD卡的扇區(qū)有關(guān),最好掌握了SDIO讀取SD卡扇區(qū)的基礎(chǔ)之后再來看這一篇帖子。
寫在前面的話
上一次發(fā)表了關(guān)于SDIO讀取SD卡的一篇開發(fā)分享的帖子,今天呢就更進(jìn)一步使用了FatFs文件系統(tǒng)。同樣我們完全使用ST公司提供的STM32CubeMX軟件和HAL庫來進(jìn)行開發(fā)。如果喜歡我的帖子請多多回復(fù)我會努力更新的。
我使用的工具
開發(fā)平臺:正點(diǎn)原子探索者STM32F407開發(fā)板
硬件:使用了NUCLEO-F446RE開發(fā)板的ST-Link作為調(diào)試器、SD卡、數(shù)據(jù)線、開發(fā)板的電源適配器、DELL一體機(jī)
軟件:STM32CubeMX、Keil V5、串口助手
學(xué)習(xí)的知識點(diǎn)
1、使用STM32CubeMX配置SDIO
2、在Keil中初始化SDIO
3、修改HEAP內(nèi)存塊的大小
4、malloc函數(shù)的使用
5、如何使用FatFs提供的一些庫函數(shù)
共享的資源
完整的工程文件FatFs.zip
STM32Cube中FatFs的中文幫助文檔
準(zhǔn)備工作
參考SDIO讀取SD卡扇區(qū)這篇帖子,這里不再贅述。
目錄
一、在STM32CubeMX中配置好我們的工程
1、配置FatFs
2、配置SDIO
3、配置SYS
4、配置USART
二、在Keil中做初始化
1、調(diào)用BSP_SD_Init()函數(shù)
2、修改MX_FATFS_Init(void)函數(shù)
三、修改啟動文件
1、malloc函數(shù)的介紹
2、FatFs對malloc函數(shù)的調(diào)用
3、改變heap的內(nèi)存大小
四、使用FatFs
1、定義一些變量
2、使用f_open
3、使用f_read
4、使用f_lseek
5、使用f_write
6、使用f_close
7、再次讀取文件內(nèi)容
五、上電測試
一、在STM32CubeMX中配置好我們的工程
1、配置FatFs
在STM32CubeMX引腳配置中,找到Configuration->MiddleWares->FatFs,勾選下面的SD Card。
2、配置SDIO
STM32CubeMX引腳配置中Peripherals->SDIO,下拉框里面選擇SD 4 bit Wide bus。
3、配置SYS
STM32CubeMX引腳配置中Peripherals->SYS,下拉框里面選擇SWD and Asynchronous Trace。
4、配置USART
STM32CubeMX引腳配置中Peripherals->USART,下拉框里面選擇Asynchronous。
下面是我的工程配置界面的截圖。
二、在Keil中做初始化
1、調(diào)用BSP_SD_Init()函數(shù)
在main函數(shù)開頭的部分調(diào)用了各種初始化函數(shù),這些函數(shù)完成了硬件的初始化工作。在我的前一篇帖子 SDIO讀取SD卡扇區(qū) 中,SDIO的初始化也是要添加一點(diǎn)代碼才可以正常的工作。這里也是一樣,不過更加的簡單。我們只需在MX_FATFS_Init();之前調(diào)用BSP_SD_Init();函數(shù)就可以了,我在下面貼出了這段初始化的代碼。
這里介紹一下BSP_SD_Init()函數(shù)。BSP的意思是板級支持包的意思,也就是這個函數(shù)是專門針對某一類芯片支持的。這個函數(shù)在文件bsp_driver_sd.c文件中,在這個文件里面還有很多的函數(shù),這些函數(shù)完成了對讀寫SD卡、查詢SD卡狀態(tài)、初始化SD卡等一系列操作。這些函數(shù)原先都是要用戶來編寫,提供給FatFs調(diào)用作為驅(qū)動支持的。但是這里幫我們都定義好了只需要調(diào)用即可,如果你要用FatFs來連接自己的設(shè)備的話,那你就需要自己定義這些底層的IO驅(qū)動函數(shù)了。
關(guān)于FatFs底層驅(qū)動支持和驅(qū)動架構(gòu)的關(guān)系請查看附件UM1721_DM00105259_CN.pdf,這里面有ST官方對這個的詳細(xì)說明。
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SDIO_SD_Init();
MX_USART1_UART_Init();
BSP_SD_Init();
MX_FATFS_Init();
復(fù)制代碼
2、修改MX_FATFS_Init(void)函數(shù)
除了上面對初始化函數(shù)的調(diào)用以外,我們還需要一些別的修改。在這里,我希望調(diào)用BSP_SD_Init()初始化好了SD卡之后,在調(diào)用MX_FATFS_Init()初始化的時候就掛載SD卡。所以我們就在FatFs的初始化函數(shù)里面用戶代碼的部分加入了我們的f_mount函數(shù)。下面貼出MX_FATFS_Init()函數(shù)的代碼,這個函數(shù)位于文件Application/User->fatfs.c中。
我還設(shè)置了一個簡單的條件語句,如果掛載SD卡成功的話就發(fā)送一個成功的消息。
void MX_FATFS_Init(void)
{
/*## FatFS: Link the SD driver ###########################*/
retSD = FATFS_LinkDriver(&SD_Driver, SD_Path);
/* USER CODE BEGIN Init */
/* additional user code for init */
if(f_mount(&SDCard, SD_Path,0) == 0)
{
HAL_UART_Transmit(&huart1, (uint8_t *)"Success!n", 9, 500);
}
/* USER CODE END Init */
}
復(fù)制代碼
OK,到了這里我們對文件的修改就基本上完成了,但是僅僅如此只能讓SD卡正常驅(qū)動和掛載,并不能夠打開文件和讀寫操作。接下來的內(nèi)容就是來解決這個問題的。
三、修改啟動文件
1、malloc函數(shù)的介紹
原型
extern void *malloc(unsigned int num_bytes);
頭文件
#include
函數(shù)聲明
void *malloc(size_t size);
備注:void* 表示未確定類型的指針,void *可以指向任何類型的數(shù)據(jù),更明確的說是指申請內(nèi)存空間時還不知道用戶是用這段空間來存儲什么類型的數(shù)據(jù)(比如是char還是int或者其他數(shù)據(jù)類型)。
功能
分配長度為num_bytes字節(jié)的內(nèi)存塊
返回值
如果分配成功則返回指向被分配內(nèi)存的指針(此存儲區(qū)中的初始值不確定),否則返回空指針NULL。當(dāng)內(nèi)存不再使用時,應(yīng)使用free()函數(shù)將內(nèi)存塊釋放。函數(shù)返回的指針一定要適當(dāng)對齊,使其可以用于任何數(shù)據(jù)對象。
以上是百度百科對malloc函數(shù)的一些簡介,在Keil中要使用這個函數(shù)需要包含stdlib.h頭文件。同時在Keil的編譯器設(shè)置中要選中microlib選項(xiàng),不過使用STM32CubeMX生成的工程默認(rèn)都選中了這一選項(xiàng)。這個函數(shù)是放在標(biāo)準(zhǔn)庫里面的,所以不能找到這個的定義代碼在哪里,編譯的時候鏈接所屬的庫就可以了。
2、FatFs對malloc函數(shù)的調(diào)用
為了討論FatFs和malloc函數(shù)的關(guān)系,我們要先打開MiddleWares/FatFs->syscall.c文件。在這個文件里面,我們可以看到有一些函數(shù)是分配內(nèi)存的函數(shù)。滾動頁面到最下面,可以看到最后兩個函數(shù)都和分配內(nèi)存有關(guān)。這些函數(shù)都調(diào)用了malloc函數(shù)來動態(tài)分配內(nèi)存,在ST的手冊中沒有提到這個malloc。但是如果沒有這個系統(tǒng)提供的malloc函數(shù)我們就需要自己來定義一個動態(tài)內(nèi)存分配函數(shù),同時把原來的malloc調(diào)用替換為我們提供的函數(shù)接口。
這樣我們就知道了FatFs對malloc函數(shù)有調(diào)用。但是僅僅如此嗎?不是這么簡單。FatFs默認(rèn)是開啟了對長文件名支持的,這樣就需要很多的內(nèi)存來存儲文件名這些信息。如果malloc內(nèi)存初始化的時候內(nèi)存設(shè)置的比較小的話,就不能成功分配內(nèi)存了不是嗎?這樣一來調(diào)用FatFs的f_open函數(shù)的時候就會返回17,查詢這個枚舉值的定義就知道是內(nèi)存分配不足的錯誤。感興趣的話可以不進(jìn)行下一步修改heap的大小來調(diào)用f_open同時把返回值發(fā)送到串口來看一看。
3、改變heap的內(nèi)存大小
malloc函數(shù)的內(nèi)存是從堆(heap)里面分配的,如果使用了對長文件名的支持我們就需要malloc為FatFs提供內(nèi)存分配的支持。在使用malloc之前會對malloc的內(nèi)存池進(jìn)行初始化,而這個初始化的操作是由我們的庫提供的啟動代碼完成的。
下面貼出匯編語言的啟動代碼的一部分。

Stack_Size EQU 0x00000400
復(fù)制代碼
這一段代碼是初始化內(nèi)存池的匯編語言代碼,在這里我把Heap_Size設(shè)置為0x00000800,也就是2KB。默認(rèn)的數(shù)值是512Bytes,這樣的話分配給我們的FatFs使用會不足,分配內(nèi)存會失敗。只有這樣子修改了之后,后面的f_open這些函數(shù)才可以正常使用。
進(jìn)行了以上的步驟之后,我們就可以輕松愉快地使用FatFs提供的各種函數(shù)了。
四、使用FatFs
1、定義一些變量
在我們代碼開始的部分,先定義一些變量供我們使用。這里選擇幾個來解析一下。
第一個FIL file;這個變量是文件的結(jié)構(gòu)體變量,記錄了我們打開的文件的信息。使用f_open等函數(shù)的時候都要用到。
第二個Words變量是一個字符串指針,我用這個指針來存儲讀取的字符信息。這里我們就使用了malloc函數(shù)來分配內(nèi)存,我們通過修改啟動代碼提供了更多的堆內(nèi)存所以這里就可以分配一些給我們使用。
第三個是Path這個字符串,這里保存的是文件所在的路徑。關(guān)于文件路徑的寫法,請參考FatFs的官方文檔網(wǎng)站。
FIL file;
復(fù)制代碼
2、使用f_open
關(guān)于f_open函數(shù)的具體用法和詳細(xì)說明,參見FatFs官方文檔網(wǎng)站。這里可以看看我在下方貼出的代碼作為參考來使用。
3、使用f_read
關(guān)于f_read沒有特別的說明,詳細(xì)的用法去看看FatFs官方文檔網(wǎng)站。這里只想說一下第三個和第四個參數(shù)。這里的第三個參數(shù)是給定的要讀取的字節(jié)數(shù),而第四個參數(shù)是最后讀取了的字節(jié)數(shù)的存儲指針。這里要說明的是,不一定你要讀取128個字節(jié)就一定會讀取這么多,如果遇到了文件尾符號就會停止讀取。停止讀取的時候就會把讀取的字節(jié)數(shù)寫入到第四個參數(shù)指定的存儲空間里。所以我們可以通過返回的讀取字節(jié)數(shù)來發(fā)送到串口,不需要自己數(shù)讀取了多少個字節(jié)。
if(!f_open(&file, Path, FA_READ | FA_OPEN_EXISTING | FA_WRITE))
復(fù)制代碼
4、使用f_lseek
我在調(diào)用f_write函數(shù)之前,調(diào)用了一下f_lseek函數(shù)來移動文件指針。不過在這里并不需要,你們參考我的完整工程文件就知道。在這之前我已經(jīng)進(jìn)行了文件讀取的操作,文件指針已經(jīng)定位在了文件的最后一個字節(jié)這里。不過我還是調(diào)用了一下,因?yàn)橛袝r候需要用到這個函數(shù)。這個函數(shù)的詳細(xì)用法請參考FatFs的官方文檔網(wǎng)站。
5、使用f_write
f_write的用法和f_read非常相似,這里就不在贅述。第三個參數(shù)和第四個參數(shù)的含義也是大同小異。想了解這個函數(shù)的詳細(xì)說明,請參考FatFs的官方文檔網(wǎng)站。
f_lseek(&file, Number);
復(fù)制代碼
6、使用f_close
f_close這個函數(shù)的用法就非常的簡單了,這里在寫入操作之后要調(diào)用一次這個函數(shù)。調(diào)用了這個函數(shù)之后,寫入的信息才可以保存在SD卡的上面,下一次才可以讀取出來。如果沒有使用這個函數(shù)的話,文件就會存儲在緩沖區(qū)中,只有這一次讀取可以成功。到了下一次復(fù)位的時候,讀取的還是原先的文件內(nèi)容。
f_close(&file);
復(fù)制代碼
7、再次讀取文件內(nèi)容
現(xiàn)在我們有寫入了一些信息到了我們的文件里面,再次讀取一下看看寫入成功了嗎。下面的代碼實(shí)現(xiàn)了這一功能,大家參考一下。
f_open(&file, Path, FA_READ | FA_OPEN_EXISTING);
復(fù)制代碼
五、上電測試
代碼我們都準(zhǔn)備好了,只要編譯通過下載到我們的開發(fā)板上就行了。如果你的硬件連接都非常的正確,而且按照前面的步驟來的話就可以開始測試讀取SD卡了。
我在SD卡的根目錄下建立了/File/test.txt
初始的文件內(nèi)容如下:
This is a test file to confirm the library of FatFs.
Don't support Chinese in this file.
Wish you a good luck!
測試結(jié)果
觀察兩次的輸出結(jié)果可以看得出來,第二次復(fù)位的時候文件的末尾又多了一行文字。這一現(xiàn)象符合我們的程序邏輯。大家可以對比一下這里的結(jié)果,自己做一個參考。
寫在后面的話
注意!注意!注意!本人不是什么工程師,只不過是愛好嵌入式開發(fā)的學(xué)生一枚,如果你發(fā)現(xiàn)在這個帖子中的錯誤請及時提醒我。如果對本帖的內(nèi)容有什么疑問請?jiān)谙路搅粞?,我會?jīng)常過來逛論壇的。
這次開發(fā)FatFs讀寫確實(shí)走了很多的彎路啊,結(jié)果最后發(fā)現(xiàn)不過是堆內(nèi)存空間不夠,不能分配的錯誤而已。為了發(fā)現(xiàn)這個錯誤我也是找了很多的資料什么的,不過這就是學(xué)習(xí)的過程吧。我覺得只有這樣才能夠鍛煉我們發(fā)現(xiàn)問題和解決問題的能力。相信在這一次又一次的坎坷和曲折之中我一定會進(jìn)步越來越大的。大家一起加油!
下一次給大家?guī)淼氖鞘裁茨??我現(xiàn)在貼出一張照片,大家一起猜一猜。
下一次要更新的東西會比較復(fù)雜的吧,所以時間可能會隔得比較久,希望期待下一篇帖子的社區(qū)成員多多關(guān)注。

 

 

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉