APP下载

基于SD卡的FAT32文件系统设计与实现

2017-07-20李敏侯亚玲刘颖

物联网技术 2017年7期

李敏++侯亚玲++刘颖

摘 要:为解决嵌入式系统中便携式存储设备的大容量数据存储问题,并便于对数据进行查询、读取及分析,系统采用具备SD卡插座的Cortex M3处理器平台,分析了SD卡的驱动实现,并按照FAT32文件系统规范进行文件系统设计。设计使用c语言进行开发,通过系统采集实时温度,并将数据按照一定的格式规范存储在SD卡的文件中;通过读取SD卡进行数据的查询、读取。经反复测试,系统运行稳定,数据的存储及读取都很可靠,且软件便于移植,可应用于大容量数据采集的系统中。

关键词:SD卡;FAT32文件系统;SPI;ds18b20

中图分类号:TP39;TN915.41 文献标识码:A 文章编号:2095-1302(2017)07-00-03

0 引 言

随着嵌入式技术的飞速发展,很多嵌入式系统都需要大容量的存储设备,用于数据存储。而当前,常用的存储设备有U盘、移动硬盘、Flash芯片、SD卡等,它们各有优缺点。综合考虑在系统设计时的性价比、功耗及体积等要求时,SD卡无疑是一个非常好的选择。随着存储技术的发展,其容量也越来越大,可以达到32 G以上,且支持SPI接口,同时SD卡有几种不同的体积可供选择,可满足不同的设计及应用要求。

具备SPI接口的嵌入式系统只需4个I/O接口就可以扩展达32 G以上的外部存储器,存储容量不等,设备更换方便,程序在不同的设备上移植也更简单。基于以上优点,SD卡在嵌入式市场得到广泛应用,成为存储设备的首选。然而SD卡中的数据以块的形式进行存储,不便于数据的组织管理,为了能够在PC端有效的对数据进行存储、管理、查询及读取,需要对SD卡进行文件系统的设计。一般而言,PC端可直接对其进行格式化后直接使用,而在嵌入式系统中,需要设计FAT文件系统对其进行数据管理。

1 SD卡驱动设计

SPI有9个引脚,支持两种操作模式,即SD卡模式(SDIO通信)和SPI模式[1]。SD卡模式允許4线的高速数据传输模式,但需要MCU带SD卡控制器,设计中会增加产品的硬件成本;SPI模式通过SPI总线接口与SD卡通信。

设计中采用的MCU为Cortex M3,它是一种低功耗、内核架构为ARM7的控制器,自带SPI控制器。处理器平台SD卡硬件连接电路均已完成,采用SPI连接方式。

系统使用SPI模式。系统上电后,设置SD卡模式转换为SPI模式。在SD卡收到复位命令(CMO)时,CS引脚被拉低,进入SPI模式。上电后,因为SD卡内部供电电压上升时间需要大约64个CLK,还需要10个CLK用于SD卡同步,在发送CMO指令前,发送至少74个系统CLK,初始化时,CLK最大不得超过400 kHz。

通过SD卡初始化就可以知道SD卡的类型,读写数据。SD卡读取数据通过 CMD17实现,具体过程如下:

(1)发送 CMD17;

(2)接收卡响应 R1;

(3)接收数据起始令牌 0XFE;

(4)接收数据;

(5)接收 2 个字节的 CRC,如果不使用CRC,这两个字节在读取后可以丢掉。

(6)禁止片选之后发送8个CLK;

SD卡的写和读数据过程基本相同,写数据通过CMD24实现[2],具体过程如下:

(1)发送CMD24;

(2)接收卡响应R1;

(3)发送写数据起始令牌0XFE;

(4)发送数据;

(5)发送2 B的伪CRC;

(6)禁止片选之后多发8个CLK。

2 FAT32文件系统介绍

为了有效管理写入SD卡的数据,使SD卡在PC机端能够被有效访问,必须将SD卡中的数据以文件形式存储,需要在SD卡中创建常用的文件系统。目前,SD卡的容量越来越大,因此设计中采用FAT32文件系统。

在设计中使用了FATFS,它是一种开源免费且专用于小型嵌入式系统的文件系统模块,硬件独立性强,是Windows系统兼容的文件系统格式,其代码特点与平台无关,支持长文件名、多种大小的扇区[3]。基于此特点,FATFS的使用非常广泛,其层次结构如图1所示。

应用层用户只需调用FATFS模块提供给用户接口函数,就可在PC机上对SD卡进行读写操作[4]。中间层FATFS模块实现了FAT文件的读/写协议,使用中一般不做修改,可直接将相关头文件包含在应用程序中。编写移植代码的是FATFS模块提供的底层接口,包括存储媒介读/写接口以及提供文件创建修改时间的实时时钟。在FATFS源码包中,需要修改的是与平台相关的代码diskio.c,即FATFS和disk I/O模块接口层文件[5]。

FATFS模块在移植时,只需修改2个文件,即ffconf.h 和 diskio.c。FATFS模块的所有配置项都存放在ffconf.h中,可以通过配置一些选项来满足设计的需求。对于SD卡的一些操作特性,可修改ffconf.h中的宏定义来实现,比如宏_FS_READONLY将其设置为0,即表示对SD卡进行读写权限的操作,_USE_MKFS为1表示使能SD卡的格式化操作等。

FATFS的移植主要分为3个步骤:

(1)在 integer.h 里定义好数据的类型;

(2)根据对SD卡的功能需要,通过 ffconf.h配置FATFS的相关功能;

(3)函数编写:打开 diskio.c以进行底层驱动编写,实现 6个接口函数的编写,如图2所示。

通过上述步骤就可以完成FATFS的移植。

3 FAT32文件系统设计

FAT32文件系统的设计包括以下步骤:

(1)程序初始化。定义两个结构体变量,其类型分别为DIR与FILINFO[6]。其中,DIR结构体表示文件夹目录相关信息,例如文件夹cewen,文件夹下有文件wendu1.txt,wendu2.txt,wendu3.txt以及文件夹cw。DIR用来存储LM、limin的目录信息,FILINFO用来存储limin1.txt,limin2.txt,limin3.txt。

DIR cewendir;//临时目录信息

FILE fileinfo;//临时文件信息

(2)程序初始化中要初始化内存,因为文件信息分配的内存空间大,一般存储在内部RAM中,也可存放在外部RAM中。先初始化内存,再申请fata所用到的变量分配内存空间。

mem_init(SRAMIN);//初始化内部内存池

exfuns_init( );//为FATFS相关变量申请内存[7]

(3)挂载SD卡。只有挂载了SD卡,才能使用,即寻找是否存在。

f_mount(0,fs[0]);//挂载SD卡

(4)打开SD卡下的文件夹,函数为FRESULT f_opendir (DIR *dj,/* 指向一个空白的结构体,用来存储要打开的文件信息,用到初始化定义的DIR型变量*/const TCHAR *path /*指向文件夹名称的指针,即打开文件的路径 */)。函数返回0 ,表示打开文件成功,否则表示打开失败[8]。

res=f_opendir ( &cewen, "0:/"); //打开 0:/cewen文件夹,文件夹的信息保存在结构体cewendir变量中,res为0,打开成功

(5)读取文件信息。在读取文件信息之前,先要申请相关变量信息的内存。

fileinfo.lfsize=_MAX_LFN*2+1; //长文件名最大长度

fileinfo.lfname=mymalloc(SRAMIN,fileinfo.lfsize);//為长文件缓存区分配内存

(6)只有成功打开文件夹,才能读取或更改文件夹下的文件,与Windows系统下的使用原理一样。判断通过res进行,即if(res==FR_OK){读取文件夹}

(7)读取文件夹函数为:FRESULT f_readdir (DIR *dj,/*指向读取的文件夹信息结构体的指针,打开文件夹后,文件夹的信息已存入信息结构体 */FILINFO *fno,/* 指向文件信息结构体,用来存储读取到的文件信息*/)。重复调用此函数可读取文件夹内的所有文件,当所有的文件读取结束后[9],函数返回一个空字符串到f_name[ ]中(文件信息结构体中的一个变量,存放名称)

if(res==FR_OK) {while(1){res = f_readdir(&lmdir,&fileinfo);//遍历文件

if(res!=FR_OK || fileinfo.fname[0]==0)

{ Show_Str(60,130,200,16,"出错了",16,0);break;}//读取出错或遍历结束,则退出

fn=(u8*)(*fileinfo.lfname?fileinfo.lfname:fileinfo.fname); printf(fn);//输出文件名} }

以上步骤是对于文件夹及文件的操作,以下步骤为文件的读写操作:

(1)打开或新建一个文件(返回值为0则成功)。

FRESULT f_open (

FIL *fp,/* 指向一个用来存储文件对象的空结构体指针*/

const TCHAR *path, /* 指向文件名的指针,即路径*/

BYTE mode /* 读取方式*/

读取方式的使用:

FA_READ读模式(读写同时生效)

FA_WRITE写模式(读写同时生效)

FA_OPEN_EXISTING默认打开方式

FA_OPEN_ALWAYS打开文件,如果不存在,则建立一个新文件;用此种方式可以用f_lseek在文件后追加数据。

FA_CREATE_NEW新建文件,如果文件已存在,则新建失败

FA_CREATE_ALWAYS新建文件,如果文件已存在,覆盖旧文件。

新建一个文件:

res=f_open(&fsrc,"0:/dongman.txt",FA_OPEN_ALWAYS); //打开,新建文件测试

if(res==FR_OK)

{

POINT_COLOR=0x2299; Show_Str(60,170,200,16,"新建文件成功!",16,0);}

f_close(&fsrc);

(2)读取文件(读取成功返回0)。

FRESULT f_read (

FIL *fp/* 指向文件对象结构体指针*/

void *buff/* 指向存储读取到的数据的缓冲区的指针 */

UINT btr/* 准备读取的字节数 */

UINT *br /* 读取到的字节数 */

f_read函数执行完后,*br值用来存放读取到的字节数,br

res=f_open(&fsrc,"0:/limin2.txt",FA_READ); // 打开,新建文件测试

if(res==FR_OK)

{

USART1_SendStr("文件内容:");

USART1_SendStr("\r\n");

while(1){

res=f_read(&fsrc,pr,256,&br);

if(res ||br < 256)

break;

USART1_SendStr(pr);

USART1_SendStr("\r\n");

Show_Str(60,170,200,16,"读取成功!",16,0); } }

f_close(&fsrc); //关闭文件,不论是打开还是新建,一定要关闭。

4 系统总体设计

系统主控核心为Cortex-M3,搭载DS18B20温度传感器[10],实现温度的实时测量,每5 s测量一次温度,将测量的数据写入SD卡的wendu.txt文件中。设计中需要实现的功能模块为DS18B20测温的驱动实现,SD卡驱动实现,SD卡fate32文件系统实现及主控任务实现,系统设计总流程如图3所示。

图3 系统设计总流程图

在设计中,SD卡Fate32文件系统的实现步骤全面可行,系统上电后,会依次初始化各相关模块。SD卡首先检测是否插接正常并给予提示。系统检测到SD卡,会挂接SD卡到主控系统并在SD卡根目录中创建一个名为wendu.txt的测温记录文档(如果已经存在,则直接打开该文档)。准备工作完成后,系统开始循环测温,并将每一次测温结果以及RTC时间格式化写入文档中。可设定文档大小,如果写入信息超过500 K,则关闭现打开文档,重新建立文档记录。

5 结 语

经测试,系统工作稳定,SD卡插接正常可稳定打开,也可以FAT32格式进行格式化。通过软件设计,可在SD卡中创建文件、打开文件、关闭文件及删除文件,所采集的数据能够正常写入文件中,并可结合RTC写入当前数据的采集时间供后续分析使用。SD卡可在PC端打开,提供采集的文本信息。设计中使用温度采集进行测试,也可按需求采集具体所需数据。FAT32文件系统的实现设计可移植性良好,可移植于单片机及各类控制器的信息采集存储系统中。

参考文献

[1]王渊,杨婧.一种基于SD卡的口令认证密钥协商方案[J].信息安全与通信保密,2014(10):88-92.

[2]刘智勇,陈鹏飞,宿磊,等.基于STM32芯片的U盘/SD卡文件传输技术研究[J].现代电子技术,2014,37(18):107-109.

[3]石长华,谢恩.基于FAT32文件系统和SD卡的陶瓷窑炉测温仪设计[J].激光杂志,2014(7):100-103.

[4]樊海洋,王立鹏,安晓捧,等.FAT32文件系统数据恢复技术的研究[J].科技信息,2013(36).

[5]夏昀.基于FAT32文件系统的安全存储方案[D].上海:上海交通大学,2013.

[6]杨明极,陈方县,吴学君.嵌入式系统中SD卡的FAT32文件系统的设计[J].电声技术,2010,34(4):36-39.

[7]顾春洋,李鑫,张强.基于SD卡的FAT32文件系统设计与实现[J].产业与科技论坛,2013,12(2):96-98.

[8]杨书凯.刘慧.一种用于高速数据采集的改进FAT32文件系统[J].信息技术与信息化,2011(6):68-70.

[9]何谐. FAT32文件系统在Cortex-M3音乐播放器中的应用[J].单片机与嵌入式系统应用,2013,13(6):71-73.

[10]袁杰,江祖敏.基于FAT32的文件隐藏方法及在Linux上的实現[J].电子设计工程,2012,20(13):15-18.