www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 單片機 > 單片機
[導(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ā)分享的帖子,今天呢就更進一步使用了FatFs文件系統(tǒng)。同樣我們完全使用ST公司提供的STM32CubeMX軟件和HAL庫來進行開發(fā)。如果喜歡我的帖子請多多回復(fù)我會努力更新的。
我使用的工具
開發(fā)平臺:正點原子探索者STM32F407開發(fā)板
硬件:使用了NUCLEO-F446RE開發(fā)板的ST-Link作為調(diào)試器、SD卡、數(shù)據(jù)線、開發(fā)板的電源適配器、DELL一體機
軟件:STM32CubeMX、Keil V5、串口助手
學(xué)習(xí)的知識點
1、使用STM32CubeMX配置SDIO
2、在Keil中初始化SDIO
3、修改HEAP內(nèi)存塊的大小
4、malloc函數(shù)的使用
5、如何使用FatFs提供的一些庫函數(shù)
共享的資源
完整的工程文件FatFs.zip
STM32Cube中FatFs的中文幫助文檔
準備工作
參考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的初始化也是要添加一點代碼才可以正常的工作。這里也是一樣,不過更加的簡單。我們只需在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官方對這個的詳細說明。
/* 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。當內(nèi)存不再使用時,應(yīng)使用free()函數(shù)將內(nèi)存塊釋放。函數(shù)返回的指針一定要適當對齊,使其可以用于任何數(shù)據(jù)對象。
以上是百度百科對malloc函數(shù)的一些簡介,在Keil中要使用這個函數(shù)需要包含stdlib.h頭文件。同時在Keil的編譯器設(shè)置中要選中microlib選項,不過使用STM32CubeMX生成的工程默認都選中了這一選項。這個函數(shù)是放在標準庫里面的,所以不能找到這個的定義代碼在哪里,編譯的時候鏈接所屬的庫就可以了。
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默認是開啟了對長文件名支持的,這樣就需要很多的內(nèi)存來存儲文件名這些信息。如果malloc內(nèi)存初始化的時候內(nèi)存設(shè)置的比較小的話,就不能成功分配內(nèi)存了不是嗎?這樣一來調(diào)用FatFs的f_open函數(shù)的時候就會返回17,查詢這個枚舉值的定義就知道是內(nèi)存分配不足的錯誤。感興趣的話可以不進行下一步修改heap的大小來調(diào)用f_open同時把返回值發(fā)送到串口來看一看。
3、改變heap的內(nèi)存大小
malloc函數(shù)的內(nèi)存是從堆(heap)里面分配的,如果使用了對長文件名的支持我們就需要malloc為FatFs提供內(nèi)存分配的支持。在使用malloc之前會對malloc的內(nèi)存池進行初始化,而這個初始化的操作是由我們的庫提供的啟動代碼完成的。
下面貼出匯編語言的啟動代碼的一部分。

Stack_Size EQU 0x00000400
復(fù)制代碼
這一段代碼是初始化內(nèi)存池的匯編語言代碼,在這里我把Heap_Size設(shè)置為0x00000800,也就是2KB。默認的數(shù)值是512Bytes,這樣的話分配給我們的FatFs使用會不足,分配內(nèi)存會失敗。只有這樣子修改了之后,后面的f_open這些函數(shù)才可以正常使用。
進行了以上的步驟之后,我們就可以輕松愉快地使用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ù)的具體用法和詳細說明,參見FatFs官方文檔網(wǎng)站。這里可以看看我在下方貼出的代碼作為參考來使用。
3、使用f_read
關(guān)于f_read沒有特別的說明,詳細的用法去看看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īng)定位在了文件的最后一個字節(jié)這里。不過我還是調(diào)用了一下,因為有時候需要用到這個函數(shù)。這個函數(shù)的詳細用法請參考FatFs的官方文檔網(wǎng)站。
5、使用f_write
f_write的用法和f_read非常相似,這里就不在贅述。第三個參數(shù)和第四個參數(shù)的含義也是大同小異。想了解這個函數(shù)的詳細說明,請參考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)在我們有寫入了一些信息到了我們的文件里面,再次讀取一下看看寫入成功了嗎。下面的代碼實現(xiàn)了這一功能,大家參考一下。
f_open(&file, Path, FA_READ | FA_OPEN_EXISTING);
復(fù)制代碼
五、上電測試
代碼我們都準備好了,只要編譯通過下載到我們的開發(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)容有什么疑問請在下方留言,我會經(jīng)常過來逛論壇的。
這次開發(fā)FatFs讀寫確實走了很多的彎路啊,結(jié)果最后發(fā)現(xiàn)不過是堆內(nèi)存空間不夠,不能分配的錯誤而已。為了發(fā)現(xiàn)這個錯誤我也是找了很多的資料什么的,不過這就是學(xué)習(xí)的過程吧。我覺得只有這樣才能夠鍛煉我們發(fā)現(xiàn)問題和解決問題的能力。相信在這一次又一次的坎坷和曲折之中我一定會進步越來越大的。大家一起加油!
下一次給大家?guī)淼氖鞘裁茨兀课椰F(xiàn)在貼出一張照片,大家一起猜一猜。
下一次要更新的東西會比較復(fù)雜的吧,所以時間可能會隔得比較久,希望期待下一篇帖子的社區(qū)成員多多關(guān)注。

 

 

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

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉