摘要:本文详细介绍了SD卡的基本结构、技术特征和FAT16文件系统的原理、组成,开发了一种基于MSP430F449单片机和SD卡的FAT16文件存储系统,对接口电路进行了设计,同时给出了软件系统的设计流程。该系统成功的应用在电量测量仪中,写入的文件能被Windows操作系统读写,在大容量的现场数据采集和存储方面有着广泛的应用前景。
关键词:MSP430F449;SD卡;FAT文件系统
0引言
随着超低功耗单片机及其应用技术的不断进步和完善,越来越多的研究者开始倾向于研究具有高速采样,实时记录数据的嵌入式仪器。这些仪器不仅要求存储介质体积大、容量大,而且要功耗低、可靠性高、存储速度快。
近几年,随着FlashMemory非易失存储技术的发展,诞生了很多基于Flash存储技术的大容量闪存卡,例如CF卡、MMC卡、SD卡等等。其中,SD卡以其体积小,功耗低的优势被广泛应用于各种数码产品中。同时其也可以作为嵌入式仪器的数据存储介质。
本文提出了基于高速低功耗MSP430单片机读写SD卡的方案,采用串行外设协议总线结构对其数据进行读写操作。
1MSP430F449与SD卡接口设计
本文微控制器选用了MSP430系列的MSP430F449单片机。MSP430系列单片机具有高效16位内核,27条指令,125ns指令周期,其内部由很多模块组成,各模块相互独立,如定时器(Timer)、输入输出口(I/O)、A/D转换、看门狗、液晶显示器等都可以在主CPU休眠的状态下独立运行。MSP430单片机工作在1.8~3.6V电压下,有正常工作模式和4种低功耗模式,在最低功耗下工作只需1.8μA,从低功耗模式下唤醒仅需6μs。此外MSP430系列单片机具有LCD驱动、A/D转换以及模拟比较器和多路中断等,用途十分广泛。MSP430单片机不但功耗低、而且速度快,更加适合高速的数据采集和处理。具有先进的JTAG技术和Flash在线编程技术,在系统设计、开发调试及实际应用方面都表现出明显的优势。
SD卡技术在MultimediaCard(MMC卡)基础上开发,具有功耗低、支持热插拔等特点,是数码产品主流的存储介质,性价比高。SD卡有9个引脚,其中7个和MMC卡在电气上兼容。
SD卡支持SPI和SD通讯方式。SPI方式通讯速率相对较慢,部分支持SD的命令集,由于SPI方式的协议比SD的简单很多,单片机可以通过内建的SPI接口或GPIO与SD卡进行SPI通讯,是低成本应用的首选方式。MSP430集成了SPI模块,需要配置在“模式0”。三线式接口由CS(片选),CLK(时钟),DI(单片机机到卡的数据信号)和DO(卡到单片机机的数据信号)构成,本系统采用MSP430F449的USART1来实现。为避免基于MOS器件技术的SD卡出现未知状态,各引脚应当正确地上拉或者下拉。由于SD卡的D3脚有可编程的内部上拉电阻(50~100kΩ,可用ACMD42命令断开),CLK信号总由MSP430驱动,出于低功耗考虑,它们不外接上/下拉电阻。SPI方式数据方向固定,通讯线宽为1,因此D2、D1脚下拉,如图1所示。
图1SD卡原理图
2软件实现
2.1SD卡的工作模式
系统的设计采用串行外设协议(SPI)的连接方式。串行外设协议消息由指令、回应和数据块组成,所有的操作均由主设备控制。主设备每次开始传送任务时,都先将片选端置低电平,以激活SD进入工作状态。SD卡由指令控制,支持特定的指令格式,且每一条指令发送后,SD卡都会有一个应答,以表明卡的状态。
2.2SD卡的初始化
SD卡的初始化流程如图2所示。SD卡上电后的默认模式是SD模式,必须通过初始化命令进入串行外设协议模式。CMD0命令被成功接收后,SD卡会向单片机返回0x01,进入idle_state模式。然后发送CMD1命令,发送成功,SD卡就会返回0x00的八位二进制数,通知主控SD卡初始化完成。
需要注意的是,SD卡在进入SPI模式前,空闲状态只接受SD命令,命令的CRC(循环冗余校验)域必须有效,进入后,缺省为内容无效;在选择进入SPI模式后,重新上电前不能返回SD模式;SPI方式中,选中的SD卡总响应命令,而不是超时。
图2SD卡初始化流程图
SD卡的部分初始化代码及子程序如下:
while(status!=0)//如果返回非空,则有错误发生或者SD卡将被再次初始化
{
status=initSD();//SD卡初始化
timeout++;
if(timeout==50)//如果有错误,则重试50次
{
printf("NoSD-cardfound!!%xn",status);//无SD卡发现
break;
}
}
while((SD_ping()!=SD_SUCCESS));//等待,直到卡插入
charinitSD(void)
{
inti;
initSPI();//初始化SPI接口及功能
CS_HIGH();
for(i=0;i<=9;i++)
spiSendByte(0xff);
return(SD_GoIdle());//返回SD卡的状态信息
}
charSD_GoIdle()
{
charresponse=0x01;
CS_LOW();//CS置低SDSendCmd(SD_GO_IDLE_STATE,0,0x95);//发送命令0使SD卡处于SPI模式
if(SDGetResponse()!=0x01)//等待准备好响应
returnSD_INIT_ERROR;//如果响应不正确,则返回SD卡错误
while(response==0x01)
{
CS_HIGH();//CS置高
spiSendByte(0xff);//SPI发送一个字节
CS_LOW();//CS置低
SDSendCmd(SD_SEND_OP_COND,0x00,0xff);//发送CMD1命令
response=SDGetResponse();//获取SD卡的响应
}
CS_HIGH();//CS置高
spiSendByte(0xff);//SPI发送一个字节
return(SD_SUCCESS);//返回SD卡初始化成功信息
}
2.3FAT16文件系统软件设计
目前,在PC机DOS/Windows的管理下,广泛使用的是FAT12、FAT16、FAT32、NTFS文件系统,FAT12一般用于软盘,FAT16、FAT32和NTFS则用于硬盘。PC机FAT文件系统分配数据是以簇为单位的,一般来说,NTFS支持大于4G单个文件,管理非常复杂;FAT32的簇要比FAT16小得多,但管理也比FAT16复杂,因此容量大于512M的采用FAT32,容量小于512M的使用FAT16。在磁盘上实际的文件分配表中每个记录所占的位数不同,FAT12占12位,FAT16占16位,FAT32则占32位。每个记录中的数据均按照低字节在前,高字节在后排列。
本系统采用FAT16文件系统。和其他FAT文件系统一样,FAT16文件系统的数据信息一般由MBR、DBR、FAT、FDT和数据区5个部分组成。
MBR(MasterBootRecord),即主引导记录,位于0柱面0磁头1扇区。DBR(DOSBootRecord)系统引导记录扇区位于逻辑0扇区。主要完成DOS/Windows的自举,占一个扇区,又被称为DOS引导扇区或BOOT区,其中,该区的BPB(BiosParameterBlock)参数块记录着分区的起始扇区、结束扇区、文件存储格式、硬盘介质描述符、根目录大小、FAT个数,分配单元大小等重要参数。文件分配表FAT紧随DBR之后,从逻辑1扇区开始,它是文件管理系统用来给每个文件分配磁盘物理空间的表格,FAT文件分配表由表标识和簇映射的集合组成,一个完全相同的镜像副本连续存储在主FAT表后,FAT的全部目的就是跟踪文件,具体描述即需要说明整个磁盘分区中的每个存储单元(簇)的使用情况、文件数据的簇存储情况(连续或碎片)以及树型目录结构的描述。FAT实际上就是一个卷中所有簇使用情况的映射表,每个文件、目录都同表中的若干项对应联系,并在目录中进行索引。FAT之后就是根目录,记录整个磁盘上所有文件的有用信息,其中每一个文件占32个字节,包括文件名、文件属性、文件的修改时间和文件的长度等等。根目录接下来是数据区,用来存储采集的数据等信息。
SD卡同时支持多块的连续读写(实际是单块连续写入的循环操作),只是写单块和写多块开始时的令牌包有所不同。SD卡多块写的流程图,如图3所示。可以看出多块写只是单块连续写的循环操作。其中单块写是否成功要看单块发送完后接受的字节的低4位是否是0101,如果是,即说明单块写操作成功。
图3多块写流程图
对指定位置的多块读操作使用CMD18命令,发送命令后,要求返回数据开始令牌包0xfe,全部数据传输完成后,没有数据,结束令牌包。其它与多块写流程类似。
下面给出关于FAT16文件系统操作的部分子函数程序代码,如下所示:
cardSize=SD_ReadCardSize();//判断SD卡的容量
ReadBPB();//读取SD卡的BPB
CreateFile("TEST0001TXT");//创建测试文件
ReadBlock(FATStartSec());//读FAT表
ReadBlock(DirStartSec());//读根目录
ReadBlock(DataStartSec());//读数据开始区
SD_GoIdle();//设置SD卡处于空闲状态
voidReadBPB(void)//读取BPB数据结构子程序
{
FAT_BPB*BPB=(FAT_BPB*)BUFFER;
ReadBlock(0); //获取参数
BPB_BytesPerSec=BPB->BPB_BytesPerSec;
BPB_SecPerClus=BPB->BPB_SecPerClus;
BPB_RsvdSeccnt=BPB->BPB_RsvdSecCnt;
BPB_NumFATs=BPB->BPB_NumFATs;
BPB_RootEntCnt=BPB->BPB_RootEntCnt;
BPB_TotSec16=BPB->BPB_TotSec16;
BPB_FATSz16=BPB->BPB_FATSz16;
BPB_HiddSec=BPB->BPB_HiddSec;
}
voidCreateFile(uint8FileName[11])//创建文件子程序
{
uint16ClusID;
DIRFileDir;
EmptyBytes(&FileDir,sizeof(DIR));
CopyBytes(FileName,&FileDir.FileName,11);
FileDir.FileAttrib=0x20;
FileDir.FilePosit.Start=GetNextFAT();
ClusID=FileDir.FilePosit.Start;
WriteFAT(ClusID,0xffff);
WriteFAT2(ClusID,0xffff);
WriteDIR(GetEmptyDIR(),&FileDir);
}
voidReadBlock(uint32LBA)//读一个扇区子程序
{
SDReadSector(LBA,BUFFER);
return;
}
voidWriteBlock(uint32LBA)//写一个扇区子程序
{
SDWriteSector(LBA,BUFFER);
return;
}
数据的读写以扇区为单位,一个簇所包含的扇区数由引导区中基本输入输出系统参数的分配表参数来决定,通过根目录找到对应的文件名,格式化完成或进行写操作时,就要新建对应文件名的文件分配表区和根目录区,通过文件分配表区中的保存的簇号,完成对应的数据读写,完成一个簇的操作后,根据文件分配表的链式结构,找到文件的待操作的下一个簇的簇号,进行相应的操作,直到文件结束。
3结束语
本文介绍的系统可以很方便的进行存储容量的扩展,而且功耗低,满足了长期大量数据存储的要求。可以很方便的应用于小型便携式嵌入式系统中,在数据采集存储方面更加灵活、稳定,摆脱了操作系统的限制。
参考文献
[1]胡大可.MSP430系列单片机C语言程序设计及开发[M].北京:北京航空航天大学出版社,2002
[2]SDGroup.SDSpecificationsPart1PhysicalLayerSimplifiedSpecification:Ver2.02006-9-25[EB/OL].[2008-03-08].http://www.sdcard.org/about/memory_card/pls/Simplified_Physical_Layer_Spec.pdf.
[3]周煜.基于SPI协议的MMC卡读写机制的实现[J].计算机仿真,2005,1(22):97-99
[4]苏义鑫,程敏,何力.基于AT89C52单片机的SD卡读写设计[J].世界电子元器件,2008,5,65-68