SD卡文件读写
SD卡文件讀寫(xiě)
象棋小子??? 1048272975
SD卡(Secure Digital Memory Card)具有體積小、容量大、數(shù)據(jù)傳輸快、可插拔、安全性好等優(yōu)點(diǎn),被廣泛應(yīng)用于便攜式設(shè)備上。例如作為數(shù)碼相機(jī)的存儲(chǔ)卡,作為手機(jī)、平板多媒體擴(kuò)展卡用的TF卡(micro sd)等等。
1. SD卡概述
SD卡技術(shù)是在MMC卡的基礎(chǔ)上發(fā)展起來(lái)的,其尺寸與MMC卡一樣,只是比MMC卡厚了0.7mm,因此SD主機(jī)可以識(shí)別并存取MMC卡。SD卡接口除了保留MMC卡的7針外,還在兩邊加了2針,作為數(shù)據(jù)線,目的是通過(guò)把傳輸方式由串行變成并行,以提高傳輸速率。此時(shí)的規(guī)范為SD1.0版本,最高容量只能到4GB。為了跟進(jìn)產(chǎn)品的更新?lián)Q代,SD聯(lián)合協(xié)會(huì)在06年發(fā)布了容量更大、存儲(chǔ)更快的下一代SD卡規(guī)范SD2.0。該規(guī)范重新定義了SD卡的速度等級(jí),分為三檔:Class 2、4、6,分別對(duì)應(yīng)寫(xiě)入速度2MB/S、4MB/S、6MB/S。根據(jù)卡容量又分為標(biāo)準(zhǔn)卡(小于2GB)和高容量卡(2GB~32GB),目前市面上應(yīng)用的SD卡絕大部分都是SD2.0版本的卡。為了讓儲(chǔ)存卡更加迷你,通過(guò)SD卡規(guī)范標(biāo)準(zhǔn),又衍生了MiniSD卡和Micro SD卡,這些卡均比標(biāo)準(zhǔn)SD卡尺寸小,通過(guò)SD轉(zhuǎn)接套可以當(dāng)作一般的SD卡使用。尤其是Micro SD卡,可以算是最小的存儲(chǔ)卡了,超小的體積可以極大的節(jié)省消費(fèi)電子產(chǎn)品內(nèi)部設(shè)計(jì)的空間,基本目前的Android手機(jī)均是選用Micro SD卡作為多媒體擴(kuò)展儲(chǔ)存卡。隨著科技的進(jìn)步,SD2.0規(guī)范SD卡也漸漸無(wú)法滿(mǎn)足應(yīng)用的需求,在10年SD聯(lián)合協(xié)會(huì)又發(fā)布了新的SD3.0規(guī)范,該規(guī)范定義了sdxc和uhs,并增加了Class10,容量范圍為32GB~2TB。在sdxc卡仍需進(jìn)一步坐等其價(jià)格下降的情況下,SD4.0規(guī)范已經(jīng)開(kāi)始在緊張的制訂中,這已超出本文的討論范圍內(nèi)了。
2. SD卡驅(qū)動(dòng)
SD卡共支持三種傳輸模式:SPI模式、1位SD模式、4位SD模式。所有的SD卡都必須支持較老的SPI/MMC模式,這個(gè)模式支持慢速的四線SPI接口,使很多微控制器都可以通過(guò)SPI或模擬SPI接口來(lái)讀寫(xiě)SD卡。萬(wàn)利的LPC5411x開(kāi)發(fā)板通過(guò)SPI接口擴(kuò)展了一個(gè)TF卡槽,可以用SPI接口讀寫(xiě)TF卡。
SD2.0標(biāo)準(zhǔn)定義了物理層相關(guān)規(guī)范以及主機(jī)控制器規(guī)范,SD卡驅(qū)動(dòng)的編寫(xiě)必須參考這兩個(gè)規(guī)范,遵循標(biāo)準(zhǔn)的SD卡均可以采用統(tǒng)一的軟件驅(qū)動(dòng)實(shí)現(xiàn)數(shù)據(jù)訪問(wèn)。NXP對(duì)于其全系列的芯片提供了sdmmc庫(kù)中間件用于支持SD/MMC卡的讀寫(xiě),可以在官網(wǎng)下載相應(yīng)的BSP,里面包含sdmmc庫(kù),fsl_sdspi.h/fsl_sdspi.c即為SPI模式訪問(wèn)SD卡的標(biāo)準(zhǔn)驅(qū)動(dòng),可以直接應(yīng)用到LPC5411x開(kāi)發(fā)環(huán)境中。SD卡驅(qū)動(dòng)最主要實(shí)現(xiàn)三個(gè)接口,分別是SD卡的識(shí)別初始化、SD卡的塊讀、SD卡的塊寫(xiě),具體實(shí)現(xiàn)可以參考fsl_sdspi.h/fsl_sdspi.c驅(qū)動(dòng)文件。
3. Fatfs
數(shù)據(jù)往往以文件的形式保存在儲(chǔ)存設(shè)備中,對(duì)于SD卡,一般采用的是Fat32文件系統(tǒng),Fatfs由于其開(kāi)源免費(fèi),支持Fat32,受到了廣泛的應(yīng)用。
Fatfs是由日本工程師ChaN所編寫(xiě)的Fat文件系統(tǒng)模塊,從06年發(fā)布第一個(gè)Fatfs版本開(kāi)始,作者就從未停止維護(hù)和更新。Fatfs的編寫(xiě)遵循ANSI C,并且完全與磁盤(pán)I/O層分開(kāi)。它不依賴(lài)于硬件架構(gòu),代碼和工作區(qū)占用空間小,使之可以嵌入到各個(gè)低成本的微控制器中,如AVR、8051、PIC、ARM、Z80、68K等。由于SD卡一般使用Fat32文件系統(tǒng),在使用到SD卡的系統(tǒng)中移植Fatfs,將很好地實(shí)現(xiàn)對(duì)SD卡文件的管理。
Fatfs模塊完全獨(dú)立于磁盤(pán)I/O層,因此底層磁盤(pán)I/O訪問(wèn)并不屬于Fatfs的模塊部分,用戶(hù)必須自己實(shí)現(xiàn)這部分用來(lái)訪問(wèn)存儲(chǔ)設(shè)備。通常在diskio.c中實(shí)現(xiàn)這幾個(gè)函數(shù)disk_initialize()、disk_status()、disk_read()、disk_wirte()、disk_ioctl()即可,如果使能了OS相關(guān)的特性,則還需額外實(shí)現(xiàn)進(jìn)程/內(nèi)存函數(shù)。其中disk_initialize()對(duì)應(yīng)SD卡驅(qū)動(dòng)中的卡識(shí)別初始化接口,disk_read()對(duì)應(yīng)SD卡的塊讀接口,disk_wirte()對(duì)應(yīng)SD卡的塊寫(xiě)接口。NXP對(duì)于其全系列的芯片提供了Fatfs中間件的支持,Fatfs對(duì)應(yīng)SD卡驅(qū)動(dòng)接口的具體實(shí)現(xiàn)可以參考BSP中已移植好的Fatfs中間件。
4. 讀寫(xiě)測(cè)試
移植好SD卡驅(qū)動(dòng)以及Fatfs底層對(duì)應(yīng)接口后,就可以用Fatfs應(yīng)用編程接口讀寫(xiě)SD卡里面的文件。應(yīng)用以2KB大小為讀寫(xiě)單位,測(cè)試讀寫(xiě)10MB大小文件的平均讀寫(xiě)速度。
uint8_t TestBuffer[2048];
int main()
{
uint32_t i;
FATFS fs;
FIL file;
FRESULT Res;?????
uint32_t TimeCount;
uint32_t ByteWrite, ByteRead;
?
?/* Board pin, clock, debug console init */
?/*attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
/* enable clock for GPIO*/
CLOCK_EnableClock(kCLOCK_Gpio0);
CLOCK_EnableClock(kCLOCK_Gpio1);
?
BOARD_InitPins();
BOARD_BootClockFROHF96M();
BOARD_InitDebugConsole();????
?
Gpio_Init();
?
f_mount(&fs, "4:" , 0);??????
/*
Res = f_mkfs("", 0, 4096);
if (Res != RES_OK) {
?????? PRINTF("f_mkfs error %d\r\n",Res);
?????? while(1);
}
*/
PRINTF("Writing test.bin, file sise10MB\r\n");
?Res= f_open(&file, "4:test.bin", FA_WRITE | FA_CREATE_ALWAYS);
if (Res != RES_OK) {
?????? PRINTF("Createfile failed\r\n");
?????? while(1){
????????????? GPIO_TogglePinsOutput(GPIO,0, 1u << 15);
????????????? Delay_ms(300);????????????????
?????? }
}
for (i=0; i<sizeof(TestBuffer); i++){
?????? TestBuffer[i]= i;
}
TimeCount =timer_get_current_milliseconds();
for (i=0;i<10*1024*1024/sizeof(TestBuffer); i++) {
?????? Res= f_write(&file, &TestBuffer, sizeof(TestBuffer), &ByteWrite);
?????? if(Res != RES_OK) {
????????????? f_close(&file);
????????????? PRINTF("Writefile error\r\n");
????????????? while(1){
???????????????????? GPIO_TogglePinsOutput(GPIO,0, 1u << 15);
???????????????????? Delay_ms(300);
????????????? }
?????? }
}
f_close(&file);
PRINTF("Sd write speed %dKB/s\r\n", 10*1024*1024/(timer_get_current_milliseconds()-TimeCount));
??????
PRINTF("Reading test.bin, file sise10MB\r\n");
Res =?f_open(&file, "4:test.bin", FA_READ | FA_OPEN_EXISTING);
if (Res != RES_OK) {
?????? PRINTF("Openfile failed\r\n");
?????? while(1){
????????????? GPIO_TogglePinsOutput(GPIO,0, 1u << 15);
????????????? Delay_ms(300);
?????? }
}
TimeCount =timer_get_current_milliseconds();
for (i=0;i<10*1024*1024/sizeof(TestBuffer); i++) {
?????? Res= f_read(&file, (unsigned char *)&TestBuffer, sizeof(TestBuffer),&ByteRead);
?????? if(Res != RES_OK) {
????????????? f_close(&file);
????????????? PRINTF("Readfile error\r\n");
????????????? while(1){
???????????????????? GPIO_TogglePinsOutput(GPIO,0, 1u << 15);
???????????????????? Delay_ms(300);
????????????? }
?????? }
}
f_close(&file);
PRINTF("Sd read speed %dKB/s\r\n", 10*1024*1024/(timer_get_current_milliseconds()-TimeCount));
?
while(1) {
?????? GPIO_TogglePinsOutput(GPIO,0, 1u << 15);
?????? Delay_ms(1000);
}
}
讀寫(xiě)速度測(cè)試結(jié)果如下:
SD卡寫(xiě)速度為872 KB/S,讀速度為1169 KB/S,SD卡通過(guò)SPI接口讀寫(xiě),SPI時(shí)鐘采用FRO 12M時(shí)鐘,因此這個(gè)讀寫(xiě)速度是合適的。SD卡讀寫(xiě)速度跟卡速度等級(jí)、數(shù)據(jù)傳輸速率有關(guān),讀寫(xiě)多塊要比一塊一塊分多次讀寫(xiě)快,此處測(cè)試一次性讀取8塊(512字節(jié)/塊),2048字節(jié),讀寫(xiě)速度主要受限于SPI的傳輸速率,LPC5411x的SPI接口最高支持48M的時(shí)鐘,SPI可以通過(guò)采用PLL時(shí)鐘、內(nèi)部高速時(shí)鐘,進(jìn)一步提高SPI的傳輸速率,從而進(jìn)一步提高SD卡的讀寫(xiě)速度。
5. 附錄
MDK工程,包含SPI模式的SD驅(qū)動(dòng),Fatfs文件系統(tǒng)模塊,SD卡讀寫(xiě)速度測(cè)試應(yīng)用例程。
https://pan.baidu.com/s/1cMz1G6
?
總結(jié)
- 上一篇: Caj转pdf有哪些不收费的转换方法?
- 下一篇: 极路由3-HC5861无拆机获取root