您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 基于STM32的FATS文件系统移植全过程
FAT移植的好文档一、移植目的1、结合命令界面的改进,实现文件系统与命令界面的结合使用。2、在命令界面中实现以下文件系统操作命令:flist-列出当前目录下的文件;fmkdir-在当前目录下创建目录;fchgdir-改变当前目录;fread-读取文件内容;fwrite-新建文件并写入。二、移植条件1、可以识别参数的串口命令界面。2、FatFS007e版本。三、对命令界面所实现功能的描述1、超级终端设置。首先打开串口终端,设置波特率115200,8位数据,无奇偶校验,无流控,终端仿真选择ANSIW,asicc码设置为以换行符结尾(以前设置的,原因已经忘了),反正这样设置了能够正常工作。开发板复位后,终端显示:**********nthq2004编写的简单命令接口!*********Sh然后可以在这里输入命令执行。比如现在支持的命令包括:help,cls,ledon,ledoff,time,temp,i2cwr,i2crd,sdrd,sdwr,共10个命令。比如输入helpme命令,则会显示命令界面当前支持的所有命令,并显示当前所有输入的命令参数。所以命令执行过程的分析以helpme为例,help是命令,me是参数。2、串口终端命令输入过程在串口终端输入一个字符时,其工作工程为:voidUSART1_IRQHandler(void){//该函数在文件stm32f10x_it.c中OS_CPU_SRcpu_sr;OS_ENTER_CRITICAL();OSIntNesting++;//中断嵌套计数OS_EXIT_CRITICAL();if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET){Uart_ReceiveChar();//串口接收字符}OSIntExit();//这里可以触发任务切换软中断}串口接收到字符引起终端、然后调用函数Uart_ReceiveChar()获取字符并放入串口消息队列,voidUart_ReceiveChar(void){//该函数在文件uart.c中u32RecChar;RecChar=(u32)(USART1-DR&0xFF);OSQPost(UartMsgOSQ,(void*)RecChar);//将字符指针化放入消息队列,这里接用了周慈航教授书中的方法。}在task_uartcmd.c文件创建的串口界面任务中,caseUartStateInput://如果出于输入状态{UartCharIn=Uart_GetChar();//读取输入按键UartCharIn&=0x7F;该函数从消息队列中取得从串口接收到的字符,然后放入到串口命令缓冲数组。UartCmdBuf[UartCharCount]=UartCharIn;//将字符存入缓冲区当前位置UartCharCount+=1;Uart_PutChar(UartCharIn);//将有效字符输出。这是在用户电脑的超级终端上进行回显。}如果用户在超级终端上按下了回车键:if(UartCharIn=='\n')//如果按下了Enter键,它是触发软件状态机从输入态{//进入命令解释执行态的关键。UartCmdBuf[UartCharCount]='\0';//命令缓冲区以0结束Uart_PutString(\r\n);//显示器上回显换行UartCmdState=UartStateExe;//如果输入过字符,进入命令解释态UartCharCount=0;}3、串口命令执行过程进入命令执行态后,首先进行命令缓冲字符串的解析,从中分析出命令和参数:caseUartStateExe://如果处于命令执行态{UartParseCmdBuf(UartCmdBuf,&CmdArg);//命令缓冲字符串的解析解析后得到一个结构数组,指明参数的个数和一个指向参数指针数组的指针:该数组的第一个指针指向命令字符串,第二个开始指向参数。UartCmdStr=CmdArg.Argv[0];//解析命令缓冲区,得到命令结构信息,我这里还只支持简单命令//所以处理很简单,直接获得命令字符串,以后可以扩展。for(UartCmdIndex=0;UartCmdIndexUartCmdMaxCount;UartCmdIndex++){//在命令表里搜索对应命令字符串UartCompResult=strcmp((char*)UartCmdStr,(char*)(UartCmdStrTable[UartCmdIndex]));//命令字符串比较的结果if(UartCompResult==0)//如果在字符串表里找到。返回0.break;//此时CmdIndex对应的值为命令在命令表里的索引。}if(UartCmdIndexUartCmdMaxCount){//找到对应命令,调用相应函数处理argc=CmdArg.Argc;for(j=0;jargc;j++){argv[j]=(void*)CmdArg.Argv[j];}UartCmdTable[UartCmdIndex].UartCmdFunc(argc,argv);//利用}实际上输入命令helpme,此时调用的函数就是:UartCmdTable[0].UartCmdFunc=UartCmdHelp;该函数的源代码在文件uartcmd.c文件中:voidUartCmdHelp(u8argc,void**argv){u8i;Uart_PutString(Youenteredtheparameter:);for(i=1;iargc;i++){Uart_PutString(argv[i]);/这是将后面的参数一一列出来。Uart_PutString();}Uart_PutString(\r\n);/这是将命令界面支持的命令列举出来。Uart_PutString(cls);Uart_PutString(ledon);Uart_PutString(ledoff);Uart_PutString(time);Uart_PutString(temp);Uart_PutString(i2cwr);Uart_PutString(i2crd\r\n);Uart_PutString(sdrd);Uart_PutString(sdwr\r\n);}四、建立文件系统命令执行框架1、添加新的命令初期目标是5个命令,为了使编写过程简化和快捷,先实现一个命令fread,文件系统移植成功后,再添加剩下的命令。u8*UartCmdStrTable[UartCmdMaxCount]={//串口命令字符串help,cls,ledon,ledoff,time,temp,i2cwr,i2crd,sdrd,sdwr,fread//先添加命令字符串};#defineUartCmdMaxCount11//现在支持11个内部命令UartCmdTable[10].UartCmdFunc=UartCmdFRead;//初始化命令数据结构,这是一个新的命令实现函数,在新的文件fileop.c中实现。该文件加入userlib组。Fileop.c中编写新的函数:voidUartCmdFRead(u8argc,void**argv){Uart_PutString(Youputthecommand:fread.\r\n);}然后在uartcmd.h中添加该函数的声明。然后Rebuild整个工程,下载程序,进行验证。在串口输入命令:fread,显示Youputthecommand:fread.说明命令添加成功。但是忘了在帮助命令中添加该命令的说明,补充一下。2、重新设计fread命令的功能和程序结构构思首先,该命令打开一个文件,读入一个扇区到缓冲区,然后在串口终端上显示;输入任意键,持续该过程。直到输入ESC键,命令执行完成,回到shell界面。这个程序内容的编写就设计到文件系统的操作了,结合以前对fatfs的分析,首先确定文件操作的流程:首先要调用函数FRESULTf_mount(BYTE,FATFS*),进行文件系统的注册,提供逻辑盘的数字序号(要小于逻辑盘个数),提供一个用户的文件系统对象指针,然后让系统内部的文件对象指针数组中对应于该文件系统序号的指针指向用户提供的文件系统对象,共其他函数使用。在使用这个函数之前,先定义一个用户的文件系统对象。然后调用函数FRESULTf_open(FIL*,constXCHAR*,BYTE),打开文件,需要提供参数文件结构对象指针和文件字符串指针。用户先定义一个文件结构对象,然后将地址传入该函数,用户利用字符串对应文件的信息填充该文件结构对象。然后就可以调用函数FRESULTf_read(FIL*,void*,UINT,UINT*);将用户指定文件的内容读入到缓冲区。程序框架如:voidUartCmdFRead(intargc,void**argv){FILFileInf;u8FileBuf[512];u16i;u32ByteToRead,ByteRead;u8res;res=f_open(&FileInf,FilePath,FA_READ|FA_OPENAWAYLS);if(res!=FR_OK){Uart_PutStr(FileOpenError!);returnres;}do{res=f_read(&FileInf,FileBuf,ByteToRead,&ByteRead);//要进去看一看,读后有没有自动调整指针。if(res!=FR_OK){Uart_PutStr(FileReadError!);return;}for(i=0;i512;i++){Uart_PutChar(FileBuf[i];}}while(Uart_GetChar()!=0x1c);}3、搭建框架因为在命令处理函数中调用了f_open等函数,所以先要包含头文件ff.h。然后在interg.h文件中做了如下改变://typedefenum{FALSE=0,TRUE}BOOL;#defineBOOLbool;//因为stm32的库中已经定义过TRUE和FALSE。voidUartCmdFRead(u8argc,void**argv){FILFileInf;u8FileBuf[512];u16i;UINTByteToRead,ByteRead;FRESULTres;res=f_open(&FileInf,argv[1],FA_READ|FA_OPEN_ALWAYS);if(res!=FR_OK){Uart_PutString(FileOpenError!);return;}do{res=f_read(&FileInf,FileBuf,ByteToRead,&ByteRead);//要进去看一看,读后有没有自动调整指针。if(res!=FR_OK){Uart_PutString(FileReadError!);return;}for(i=0;i512;i++){Uart_PutChar(FileBuf[i]);}}while(Uart_GetChar()!=0x1B);}然后单独编译fileop.c,成功。4、加入文件系统文件接下来在工程里面加入fatfs文件中,将ff.c和diskio.c两个文件加入,然后单独进行编译,看有没有什么问题。#defineBOOLbool;这个后面千万不能加分号,否则就会出问题。#includestm32f10x_type.h在integer.h前面要加入stm32库中数据类型的定义,因为#defineBOOLbool这句定义要用到bool的原定义。然后单独编译ff.c,成功,没有错误。单独编译diskio.c,没有错误,但有很多警告,主要是底层驱动函数还没有定义和声明。接下来的工作就是编写底层驱动了。五、diskio.c中底层驱动程序的编写。首先删除有关USB、MMC、ATA的定义,因为我这个板上只有SD卡。1、disk_initialize函数DSTATUSdisk_initial
本文标题:基于STM32的FATS文件系统移植全过程
链接地址:https://www.777doc.com/doc-4938739 .html