Petit FatFs是FatFs的简版,可以移植到8位单片机上,我此次试验是在PIC16F877A上移植了这种文件系统,用于管理SD卡中的txt文件内容的读写。其中SD卡的驱动程序在另一篇博客中有所介绍。
我在这次试验遇到的问题和想法简述于下,希望对过客有所帮助,也望高手赐教。
1.文件系统中,最为根本的就是底层驱动程序的编写,一般没有必要去过多研读系统本身,而且也很难读懂,我们只想调用接口函数,将自己的驱动函数程序挂在接口函数内。然后调用接口函数实现目标即可。
2.要用文件系统给sd卡里的txt文件写东西,必须先给文件写入需要文件大小的空格,因为在官方的说明中给文件写东西,不能扩大文件的大小。不知道我是不是错了,如果我没错的话,我感觉这是小文件系统的缺陷。它不能创建文件,也不能更改文件的大小。所以,我给sd卡里的txt文件预先写好东西,拿单片机在给文件写入东西的时候,会把原有的东西覆盖。如果我在文件里什么都不写,那么单片机也写不进去任何东西。如果我在文件里输入许多空格,那么单片机就会写入东西,文件指针移动的操作也可以实现。这是经过试验的。
3.在对sd卡的读写需要一定的时序,在没有移植文件系统的时候,我以前的程序可以对sd卡正常操作。但是挂到系统上之后,程序就会卡在某个循环语句处。于是我在程序中用串口发送信息的方式检测程序卡在了那里。
开始我在检测点发送的东西较少,会频繁的卡在一个地方,最后误打误撞,我将发送的内容增加,却调试成功,我也不知道是什么原因,于是在卡点放了一个延迟函数。程序便好用了起来。
一下是接口函数的书写:
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for Petit FatFs (C)ChaN, 2009 */
/*-----------------------------------------------------------------------*/
#include <pic.h>/*Platform dependent macros and functions needed to be modified */
#include<string.h>
#include "pff.h"//include "integer.h"
#include "diskio.h"//include "integer.h"
#define CS RC2
#define _XTAL_FREQ 12000000
/*************************************usart*************************************/
void init_pic_usart(void)
{
TRISC7=1;
TRISC6=1;
RCSTA=0x90;//1001 0000,SPEN=1,serial port enabled.CREN=1,
TXSTA=0X24;//0010 0100,TX9=0,select 8 bits transmission.
//TXEN=1,transmit enabled .
//SYNC=0,Asynchronous mode.
//BRGH=1,High speed.
SPBRG=77;
}
void usart_send_byte(CHAR data)
{
TXREG=data;
while(!TRMT);
}
void usart_send_str(const UCHAR *buff,UCHAR EnterFlag)//send of string,and then line feed
{
UINT i;
UINT len=strlen(buff);//count the string length
for(i=0;i<len;i++)
{
usart_send_byte(buff[i]);
}
if(1==EnterFlag)
{
usart_send_byte(0x0a);
usart_send_byte(0x0d);//line feed
}
}
/************************************SPI***********************************************/
void init_pic_spi()
{
TRISC2=0;//CS
TRISC3=0;//SCK
TRISC4=1;//SDI
TRISC5=0;//SDO
SSPSTAT=0X80;
//SMP=1,input data sampled at the end of data output time
//CKE=1;transmit occurs on transition from idle to active clock
SSPCON=0X30;
//SSPM3-SSPM0 0000 SPI master mode ,clock=fosc/64
//CKP=1 idle state for clock high level
//SPEN=1 enable serial port
//WCOL=0 no collision
//falling edge of SCK transmit data
}
void write_command(UCHAR command,DWORD arguement,UCHAR CRC)
{
UCHAR arg[4],i=0;
arguement=arguement<<9;
arg[0]=(UCHAR)(arguement>>24);
arg[1]=(UCHAR)(arguement>>16);
arg[2]=(UCHAR)(arguement>>8);
arg[3]=(UCHAR)(arguement);//four 0x00
SSPBUF=command|0x40;
while(!BF);
for(i=0;i<4;i++)
{
SSPBUF=arg[i];
while(!BF);
}
SSPBUF=CRC;
while(!BF);
}
UCHAR receive_response()
{
UCHAR a=0;
while(a++<100)
{
SSPBUF=0XFF;//if we want to read a data,must send first,we send complete,receive comlete
while(!BF);//receive flag
if(0x01==SSPBUF)
{
break;
}
else if(0x00==SSPBUF)
{
break;
}
else if(0xfe==SSPBUF)
{
break;
}
else if(0xff!=SSPBUF)
{
break;
}
}
return SSPBUF;
}
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (void)
{
DSTATUS stat;
// Put your code here
stat=RES_ERROR;
int i=0;
do
{
CS=1;//disable sd card
for(i=0;i<15;i++) //more than 74 clock pules,15*8=120,FOR YU JU CUO LE
{
SSPBUF=0XFF;
while(!BF);
}
CS=0;
SSPBUF=0XFF;
while(!BF);//8 clock
write_command(0x00,0,0x95);
}while(receive_response()!=0x01);
CS=1;
SSPBUF=0XFF;//8 clock pules
while(!BF);//untile now ,reset completed
do
{
CS=0;
__delay_us(10);
write_command(0x01,0,0xff);
}while(receive_response()!=0x00);
CS=1;
__delay_us(10);
SSPBUF=0XFF;//8 clock pules
while(!BF);//untile now ,SD card has came into SPI work mode
stat=RES_OK;
return stat;
}
/*-----------------------------------------------------------------------*/
/* Read Partial Sector */
/*-----------------------------------------------------------------------*/
DRESULT disk_readp(
BYTE* dest, /* Pointer to the destination object */
DWORD sector, /* Sector number (LBA) */
WORD sofs, /* Offset in the sector */
WORD count /* Byte count (bit15:destination) */
)
{
DRESULT res;
// Put your code here
res=RES_ERROR;
UINT i=0;
do
{
CS=0;
SSPBUF=0XFF;
while(!BF);//8 clock
write_command(0x11,sector,0xff);//CMD17:the command of read data block,address must be integer multiple of 512
}while(receive_response()!=0x00); __delay_us(100);//usart_send_str("haha,here",1);//must have
当时便卡在了此处,我的测试发送程序是usart_send_str("haha,here",1)时,程序便畅行无阻,于是我在此次加了延时函数__delay_us(100)。
while(receive_response()!=0xfe);
for(i=0;i<sofs;i++)
{
SSPBUF=0XFF;
while(!BF);//skip sofs bytes
}
for(i=0;i<count;i++)//read count byte
{
SSPBUF=0XFF;
while(!BF);//skip sofs bytes
*(dest+i)=SSPBUF;
}
for(i=0;i<512-sofs-count;i++)
{
SSPBUF=0XFF;//skip reminder bytes
while(!BF); //abandon two CRC bytes
}
SSPBUF=0XFF;
while(!BF); //abandon two CRC bytes
SSPBUF=0XFF;
while(!BF);
CS=1;
SSPBUF=0XFF;
while(!BF);//8 clock
res=RES_OK;
return res;
}
/*-----------------------------------------------------------------------*/
/* Write Partial Sector */
/*-----------------------------------------------------------------------*/
DRESULT disk_writep(
const BYTE* buff, /* Pointer to the data to be written, NULL:Initiate/Finalize write operation */
DWORD sc /* Sector number (LBA) or Number of bytes to send */
)
{ /*buff=0,sc=0 finish the write function */
/*buff=0,sc!=0 init write sector */
/*buff!=0,sc=!0 normal write */
DRESULT res;
WORD bc;//typedef unsigned short WORD;
static WORD wc;//init with 0 and keep the value last time
res=RES_ERROR;//init res
if(buff)
{ /* Send data bytes */
bc=(WORD)sc;
while(bc&&wc)
{ /* Send data bytes to the card */
SSPBUF=*buff++;
while(!BF);
wc--;bc--;
}
res=RES_OK;
}
else
{
if(sc)/* Initiate sector write process */
{
do
{
CS=0;
SSPBUF=0XFF;
while(!BF);//8 clock pules
write_command(0x18,sc,0xff);//CMD24
}while(receive_response()!=0x00);
SSPBUF=0XFF;
while(!BF);
SSPBUF=0XFE;
while(!BF);//head data
wc=512; /* Set byte counter */
res=RES_OK;
}
else
{ /* Finalize sector write process */
bc=wc+2;
while(bc--)
{
SSPBUF=0x00; //if the pointer is not on the sector boundary,left bytes should filled with 0
while(!BF);/* Fill left bytes and CRC with zeros */
}
while(0x05==(receive_response()&0x1F));
while(receive_response()!=0xFF);
res = RES_OK;//!= prior to &&,while sdcard is busy ,dataout is low
CS=1;
SSPBUF=0xff;
while(!BF);
}
}
return res;
}