求教:不能正确创建文件

我用CH375采集数据然后写进U盘。I/O引脚模拟8位并行总线读写,库是“CH375HF5.H” 字节读写的方式。大致的流程是:先用CH375FileCreate创建一个文件(文件名是可以变的),然后我有一个定时中断,差不多每隔3秒向这个文件写64B数据(用的是 ByteWrite),若干次后用CH375FileClose关闭文件,在关闭之前 mCmdParam.Close.mUpdateLen = 1; 更新长度。 还有U盘是格式化成FAT16的形式。 现在遇到的问题是: 问题1:经常写完文件在计算机上打不开,用磁盘工具看了一下,文件长度、时间等都正确 但初始簇的位置不对。比如,文件长是180字节,位于02簇,但在FAT表里,该目录项的最后 是:…………02 00 XX B4 00 00 00,就是说多了个XX(XX是一个随意的16进制数)使得文 件的初始簇变成了XX00(本来应该是0002),所以文件肯定是打不开的。 问题2:当创建第二个文件的时候,该目录项不是写了一个新的32字节,而是从上一个目录 项的最后一个字节开始写。如上例,变成了…………02 00 B4 00 00 YY(YY是新文件名第一个字符的ASCII码)这样,原有的第一个文件长度肯定是不对了(变成了YY0000B4), 而新文件所有的目录项内容都往前错了一个字节,所以全部不对了。 问题3:在定时中断中用字节方式往文件里写数据,但不是每次都能写成功,常出现的错误 有1F等,且有一定的随机性。 请教这三个问题是什么原因造成的?怎样解决,谢谢!

应该是I/O模拟时序有问题,导致数据字节错位或者错误,贴出来看看吧


多谢,将延时加长了一些,问题1和2好像有明显改善,问题3还经常出现,而且一般是出现在第一次或最后一次往文件里写数据的时候,而且如果是第一次没写成功,以后各次都不会成功。我把我的程序贴在下边,麻烦各位高手给看一下,谢谢。MPU用的是ADI的ADuC847,晶振是12.58M #include #include #include ".\ADuC845.h" #define MAX_BYTE_IO 64 #define LIB_CFG_FILE_IO 1 // "内部复制" #define LIB_CFG_INT_EN 0 // "查询方式" #define DISK_BASE_BUF_ADDR 0x0000 #define CH375_INT_WIRE #include ".\CH375HF5.H" UINT16D mIndex; UINT16D mCount; sbit CH375_A0 = P2^6; sbit CH375_CS = P2^7; sbit CH375_WR = P3^6; sbit CH375_RD = P3^7; sbit MYLED = P3^5; void mDelay1_2uS( ) // 延时1.43uS { UINT8 i; for(i=0;i<2;i++); return; } void mDelay100mS( ) // 延时100ms { UINT8 i, j, c; for ( i = 400; i != 0; i -- ) for ( j = 200; j != 0; j -- ) c+=3; } void CH375_PORT_INIT( ) // 通用I/O初始化 { CH375_WR = 1; CH375_RD = 1; CH375_CS = 1; CH375_A0 = 0; P0 = 0xFF; } void xWriteCH375Cmd( UINT8D mCmd )// 向CH375写命令 { CH375_PORT_INIT(); mDelay1_2uS( ); mDelay1_2uS( ); P0 = mCmd; CH375_A0 = 1; CH375_CS = 0; CH375_WR = 0; CH375_CS = 0; CH375_PORT_INIT(); mDelay1_2uS( ); mDelay1_2uS( ); } void xWriteCH375Data( UINT8D mData )// 向CH375写数据 { CH375_PORT_INIT(); P0 = mData; CH375_A0 = 0; CH375_CS = 0; CH375_WR = 0; CH375_CS = 0; CH375_PORT_INIT(); mDelay1_2uS( ); } UINT8 xReadCH375Data( void )// 从CH375读数据 { UINT8 mData; CH375_PORT_INIT(); mDelay1_2uS( ); P0 = 0xFF; CH375_A0 = 0; CH375_CS = 0; CH375_RD = 0; CH375_CS = 0; mData = P0; CH375_PORT_INIT(); return( mData ); } void mStopIfError( UINT8D iError )// 检查操作状态 { if ( iError == ERR_SUCCESS ) return; printf( "Error: %02X\n", (UINT16)iError ); } void mInitSTDIO( ) //初始化串口 { SCON = 0x50; PCON = 0x80; TMOD = 0x20; TH1 = 0xae; // 12.58MHz晶振, 9600bps TR1 = 1; TI = 1; } //每秒一次TIC中断, 在字节方式写数据进文件 void TIC_int () interrupt 10 { UINT8D i; UINT32D temp; //以下是AD/DA的操作 DACH = 0x00; DACL = 0x80; temp=0; for(i=0;i<4;i++) { RDY0 = 0; ADCMODE = 0x22; while (!RDY0); // 等结果 temp+=(((UINT32)ADC0H)<<16) | (((UINT32)ADC0M)<<8) | ((UINT32)ADC0L); } temp/=4; //得到的temp是一个24位的AD采样值,前边加了个02凑成4字节 //mIndex是缓冲区中数据的索引 //mCount是一个计数,假定其等于3时完成采样 mCmdParam.ByteWrite.mByteBuffer[mIndex]=0x02; mIndex++; mCmdParam.ByteWrite.mByteBuffer[mIndex]=(UINT8)temp/256/256; mIndex++; mCmdParam.ByteWrite.mByteBuffer[mIndex]=(UINT8)((temp/256) & 0xff); mIndex++; mCmdParam.ByteWrite.mByteBuffer[mIndex]=(UINT8)(temp & 0xff); mIndex++; //凑够64字节写一次U盘,每中断一次得到4字节,16秒64字节 if (mIndex==64) { mIndex=0; mCmdParam.ByteWrite.mByteCount = 64; i = CH375ByteWrite( ); mStopIfError( i ); //自动更新长度,加不加好像区别不大 mCmdParam.ByteWrite.mByteCount = 0; i = CH375ByteWrite( ); mStopIfError( i ); mCount++; //每写一次加一,共写3次,即48秒 } //通过串口得到一个时钟 printf("%d:%d:%d\n",(UINT16)HOUR,(UINT16)MIN,(UINT16)SEC); } main( ) { UINT16D dumy,fname; UINT8D filename[13]; //="Samp_000.EGG";文件名是可变的"Sample_XXX.EGG"是数据文件 //以下是我的MPU的一些配置, 与U盘有关的是有一个秒定时器, 每秒钟产生一个中断,中断函数为:TIC_int() CFG845 = 0x01; PLLCON = 0x00; MYLED=1; mInitSTDIO( ); ADC0CON1 = 0x07; ADC0CON2 = 0x4D; ADCMODE = 0x20; RDY0=0; DACCON = 0x03; DACH = 0x00; DACL = 0x80; IEIP2 = 0x04; //使能TIC TIMECON = 0xd0; //秒计数 INTVAL = 0x01; //利用MPU本身的数据FLASH,存储一个数字, //这个数字用于文件名,且每写一个新文件后就加1 EADRH=0x00; EADRL=0x00; ECON=0x01; for(dumy=0;dumy<100;dumy++); fname=EDATA2; if (fname==255) fname=0; fname++; EDATA2=fname; ECON=0x05; for(dumy=0;dumy<24000;dumy++); ECON=0x02; for(dumy=0;dumy<1000;dumy++); strcpy(filename,"Samp_000.EGG"); //先让filename是"samp_000.egg" //然后根据flash中存的数修改"000",得到不同的文件名 filename[5]=fname/100+0x30; filename[6]=(fname/10)%10+0x30; filename[7]=((fname%100)%10)+0x30; printf("%s\n",filename); //通过串口看到的文件名正确 //以下与U盘创建文件有关 CH375_PORT_INIT( ); printf( "Start\n" ); dumy = CH375LibInit( ); printf( "init OK\n" ); mStopIfError( dumy ); //等待U盘插入 printf( "Wait Udisk\n" ); while ( CH375DiskStatus != DISK_CONNECT ) xQueryInterrupt( ); printf( "Udisk in\n" ); mDelay100mS( ); // 延时,可选操作 mDelay100mS( ); MYLED=0; //检查U盘是否准备好 for ( dumy = 0; dumy < 10; dumy ++ ) { mDelay100mS( ); if ( CH375DiskReady( ) == ERR_SUCCESS ) { break; } } // 如果文件已经存在则添加数据到尾部,如果不存在则新建文件 strcpy(mCmdParam.Open.mPathName, filename); printf( "%s\n",filename ); dumy=CH375FileOpen( ); // 打开文件 if ( dumy == ERR_SUCCESS ) { printf( "File size = %ld\n", CH375vFileSize ); printf( "Locate tail\n" ); mCmdParam.ByteLocate.mByteOffset = 0xffffffff; dumy = CH375ByteLocate( ); mStopIfError( dumy ); } else if ( dumy == ERR_MISS_FILE ) // 新建文件 { printf( "Create\n" ); strcpy(mCmdParam.Create.mPathName, filename ); printf( "%s\n",filename ); dumy = CH375FileCreate( ); // 新建文件 mStopIfError( dumy ); } else mStopIfError( dumy ); // 打开文件时出错 mCount=0; mIndex=0; EA=1; TIMECON = 0xd3; //启动TIC do { }while(mCount!=3); TIMECON = 0xd0; //关闭TIC mCount=0; mIndex=0; //自动计算文件长度 mCmdParam.Close.mUpdateLen = 1; dumy = CH375FileClose( ); // 关闭文件 mStopIfError( dumy ); MYLED=0; printf( "Take out\n" ); //等待U盘拔出 while ( CH375DiskStatus != DISK_DISCONNECT ) xQueryInterrupt( ); while(1); } 还遇到一个问题,如果文件是文本的就可以从U盘拷贝到应该,如果文件是数据,拷贝进硬盘的时候报“U盘文件读写错误”,但是用磁盘工具看好像又没什么错误。(U盘格式化成FAT16的)


ch375hf5一般用串行方式,你用ch375hf6试一下,他支持并行方式。 #define MAX_BYTE_IO 64 不要用64了,用32试一下

最后的问题,我有些不太明白,都是字节读写,文本都可以,数据有什么不可以的呢


文本内容是ASCII字符,数据内容有非ASCII字符,以文件方式操做就出错。 这么说对不对?

[Emot]7[/Emot]


数据文件肯定是非ASCII字符的,问题是我并不是用记事本之类的去打开它,而是想把它从U盘拷到硬盘,这个应该和文件的格式内容无关的吧? 请教Johnny.Yang, HF6支持IO引脚直接读写的方式吗?谢谢!


刚才又试了一下,文本方式也不行。就是说用磁盘工具看文件是正常的,但是想在计算机上打开或者拷贝文件就是不行。想了一下,问题不是由于字节方式造成的,如果我用字节方式一气把文件写完就没问题。问题出在我是在定时中断里每隔一秒写一次文件,造成的,但是是什么原因?请教各位。


找到问题了,如果文件名是固定不变的话就完全正常了。但是我需要创建多个文件,怎么办呢?


两个问题, 一是模拟I/O时序可能会有问题,感觉你程序太慢,如果CPU较快那么P0端口可能要加上拉, 严格参考MCS51/FILELIB7/EXAM7中的,只需要调整延时子程序 二是文件名,Samp_000.EGG不行,必须全用大写字母SAMP_000.EGG, 否则文件看起来存在,但文件打不开、复制不了

修改好程序后,先重新格式化U盘(之前试验导致U盘数据有误)再试验,确保你没问题


找到问题了,是AD采样时间过长造成的,采4次的时间已经超过1秒了,所以中断不可靠。 文件名都改为大写后还是偶尔会出错,索性把文件名固定了,而且数据都改成了文本格式,现在用起来还不错 谢谢!


只有登录才能回复,可以选择微信账号登录