如果一个文件越大的话是不是后面添加的数据需要的时候越长? 我现在是每5秒往U盘中存一次数据,每次存储12KB。 现在实时运行, 刚开始的时候存储速度还可以, 几百毫秒就搞定,现在需要近两秒才写进去。目前文件是30MB左右,我想如果文件到了100MB写起来岂不是更慢?
有可能会产生这种情况,但是您描述的速度太慢了,这样吧,你把程序贴出来看看有什么需要修改的地方.
代码如下,中断采集数据,200Hz, my_buffer[]做数据缓冲区。
每次把数据写入u盘后把未写入的数据移至&my_buffer[1024], 而文件尾的零头数据导至&my_buffer[1024]前。 然后设置mDataBuffer指针用CH375FileWriteX()写入。
//------------------------------------------
//#include "REG52.H" #include "GSSC.H" #include #include #include
#define ulong unsigned long #define uint unsigned int #define uchar unsigned char
// 磁盘读写的数据的复制方式,1为"单DPTR复制",2为"双DPTR复制",3为"单DPTR和P2+R0复制" #define LIB_CFG_DISK_IO 1 // 文件读写的数据的复制方式,0为"外部子程序",1为"单DPTR复制",2为"双DPTR复制",3为"单DPTR和P2+R0复制" #define LIB_CFG_FILE_IO 1 // CH375的INT#引脚连接方式,0为"查询方式",1为"中断方式" #define LIB_CFG_INT_EN 0 // CH375命令端口的I/O地址 #define CH375_CMD_PORT_ADDR 0xB001 // CH375数据端口的I/O地址 #define CH375_DAT_PORT_ADDR 0xB000 // 外部RAM的磁盘数据缓冲区的起始地址,从该单元开始的缓冲区长度为SECTOR_SIZE #define DISK_BASE_BUF_ADDR 0x0400 // 默认的磁盘数据缓冲区大小为1024字节,建议选择为2048甚至4096以支持某些大扇区的U盘, // 为0则禁止在.H文件中定义缓冲区并由应用程序在pDISK_BASE_BUF中指定 #define DISK_BASE_BUF_LEN 4096 // 外部RAM的文件数据缓冲区的起始地址,缓冲区长度不小于一次读写的数据长度 #define FILE_DATA_BUF_ADDR 0x1400 // 外部RAM的文件数据缓冲区,缓冲区长度不小于一次读写的数据长度,本例要求不小于0x400即可 //#define FILE_DATA_BUF_LEN 0x5000 // P3.2, CH375_INT, CH375的中断线INT#引脚,连接CH375的INT#引脚,用于查询中断状态 #define CH375_INT_WIRE CH375_INT // 未调用CH375FileEnumer程序故禁止以节约代码 #define NO_DEFAULT_CH375_F_ENUM 1 // 未调用CH375FileQuery程序故禁止以节约代码 #define NO_DEFAULT_CH375_F_QUERY 1
#include "CH375HF6.H"
#define SAMPL 0x7A // 定时器产生200Hz的中断 #define SAMPH 0x94
uchar xdata my_buffer[0x6400] _at_ FILE_DATA_BUF_ADDR; // 数据缓冲区
unsigned char bdata adsDataH = 0; sbit adsDataH0 = adsDataH^0; sbit adsDataH1 = adsDataH^1; sbit adsDataH2 = adsDataH^2; sbit adsDataH3 = adsDataH^3; sbit adsDataH4 = adsDataH^4; sbit adsDataH5 = adsDataH^5; sbit adsDataH6 = adsDataH^6; sbit adsDataH7 = adsDataH^7; unsigned char bdata adsDataM = 0; sbit adsDataM0 = adsDataM^0; sbit adsDataM1 = adsDataM^1; sbit adsDataM2 = adsDataM^2; sbit adsDataM3 = adsDataM^3; sbit adsDataM4 = adsDataM^4; sbit adsDataM5 = adsDataM^5; sbit adsDataM6 = adsDataM^6; sbit adsDataM7 = adsDataM^7; unsigned char bdata adsDataL = 0; sbit adsDataL0 = adsDataL^0; sbit adsDataL1 = adsDataL^1; sbit adsDataL2 = adsDataL^2; sbit adsDataL3 = adsDataL^3; sbit adsDataL4 = adsDataL^4; sbit adsDataL5 = adsDataL^5; sbit adsDataL6 = adsDataL^6; sbit adsDataL7 = adsDataL^7;
uint total; uint newDataNum; uint resDataNum;
unsigned char bdata iicTemp = 0; sbit iicTemp0 = iicTemp^0;
uchar xdata DisplayDataBuf[4][16] = 0; uchar xdata TimeBuf[15] = 0;
uchar idata DateTime[7]; uchar idata ADCData[4];
#define LED_OUT_INIT() {LED1 = 1;} #define LED_OUT_ACT() {LED1 = 0;} #define LED_OUT_INACT() {LED1 = 1;}
#define LED_RUN_ACT() {LED2 = 0;} #define LED_RUN_INACT() {LED2 = 1;}
#define LED_WR_ACT() {LED1 = 0;} #define LED_WR_INACT() {LED1 = 1;}
//-------子函数实现区------- void SystemInit(void) {
// ES = 1; //串口中断允许
TMOD = 0x21; //定时器1自动重载方式,定时器0工作在方式1(16位计数) TL1 = 0xEE; //6T模式,设置波特率9600 TH1 = 0xEE; SCON = 0x50; //串口工作在方式2(10位异步收发) PCON = 0x00; //电源控制器寄存器设置 TR1 = 1; //启动T1计数(启动波特率计数) // 定时器产生200Hz中断 TL0 = SAMPL; TH0 = SAMPH; ET0 = 1; // 定时器0中断允许
EA = 1; // CPU中断允许 TR0 = 1; // 启动定时器1记数 AUXR = AUXR | 0x02; //禁止访问内部扩展RAM
}
void SendOneByte(unsigned char temp) { SBUF = temp; while(TI == 0); TI = 0; }
void Delay(unsigned int t) // Delay about 3.5 uS { do { _nop_(); }while(t--); }
uchar mCopyCodeStringToIRAM(uchar idata *iDestination, uchar code *iSource) { uchar i = 0; while(*iDestination = *iSource) { iDestination++; iSource++; i++; } return i; }
uint mCopyXRAMtoXRAM(uchar xdata *iDestination, uchar xdata *iSource, uint num) { uint i = 0; for(i = 0; i < num; i++) { *iDestination = *iSource; iDestination++; iSource++; } return i; }
uchar mCopyIRAMtoXRAM(uchar xdata *iDestination, uchar idata *iSource, uchar num) { uchar i = 0; for(i = 0; i < num; i++) { *iDestination = *iSource; iDestination++; iSource++; } return i; }
void SendString(uchar code *iString) { while(*iString) { SendOneByte(*iString); iString++; } }
void SendRAMString(uchar xdata *pString) { while(*pString) { SendOneByte(*pString); pString++; } }
void mStopIfError(uchar iError) { if(iError == ERR_SUCCESS) return; // 操作成功 while(1) { LED_OUT_ACT(); // LED闪烁 Delay(10000); LED_OUT_INACT(); Delay(10000); } }
void mFlushBufferToDisk(uchar force) { uchar i; ulong NewSize; // ulong datCount; if(force) // 强制刷新 { // 将缓冲区中的字节数转换为扇区数(除以CH375vSectorSize),长度加上CH375vSectorSize-1用于确保写入最后的零头数据 total = newDataNum + resDataNum; // 新数据字数 + 旧零头数据字节数 // datCount = total & ~(CH375vSectorSize - 1); // 数据整扇区字节数 mCmdParam.Write.mSectorCount = (total + CH375vSectorSize - 1) / CH375vSectorSize; // 以扇区为单位向文件写入数据,写入缓冲区中的所有数据,含最后的零头数据 mCmdParam.WriteX.mDataBuffer = &my_buffer[1024] - resDataNum; i = CH375FileWriteX(); mStopIfError(i); // 有些U盘可能会要求在写数据后等待一会才能继续操作,所以如果在某些U盘中发生数据丢失现象,建议在每次写入数据后稍作延时在继续操作 Delay(2000); TR0 = 0; // T0 停止记数 // 把数据存储过程中采样的数据移到缓冲区首部 mCopyXRAMtoXRAM(&my_buffer[1024], &my_buffer[1024] + total - resDataNum, newDataNum + resDataNum - total); // 缓冲区中零头数据字节数 newDataNum = newDataNum + resDataNum - total; // 缓冲区中只剩下刚才已写入U盘的零头数据,继续保留在缓冲区中是为了方便以后在其后面追加数据 total &= CH375vSectorSize - 1; TR0 = 1; // T0 启动记数 // if(total) // 以扇区为单位,有零头数据,计算出真正的文件长度(有效数据的长度) NewSize = CH375vFileSize - CH375vSectorSize + total; else // 以扇区为单位,没有零头数据,文件长度是CH375vSectorSize的倍数 NewSize = CH375vFileSize; // 输入参数: 新的文件长度,扇区模式下涉及到零头数据不便自动更新长度 mCmdParam.Modify.mFileSize = NewSize; // 输入参数: 新的文件属性,为0FFH则不修改 mCmdParam.Modify.mFileAttr = 0xFF; // 输入参数: 新的文件时间,为0FFH则不修改 mCmdParam.Modify.mFileTime = 0xFFFF; // 输入参数: 新的文件日期,为0FFH则不修改 mCmdParam.Modify.mFileDate = 0xFFFF; // 修改当前文件的信息,修改文件长度 i = CH375FileModify(); mStopIfError(i); // 移到文件的尾部,以扇区为单位,所以会忽略文件尾部的零头数据 mCmdParam.Locate.mSectorOffset = 0xFFFFFFFF; // 重新回到原文件的尾部,下面如果再写入数据将覆盖尾部零头数据,不过该零头数据有一份副本保留在缓冲区中 i = CH375FileLocate(); mStopIfError(i); } }
void ServiceT0(void) interrupt 1 {
// 重置计数器 TL0 = SAMPL; TH0 = SAMPH; // 读取时间转换为ASC码 read_rtc(); newDataNum += mCopyIRAMtoXRAM(&my_buffer[1024] + newDataNum, &DateTime[0], 6); // 读取ADC值并转换为ASC码 // ch1 ================================ AD_CHS0 = 0; AD_CHS1 = 0; Delay(1); ReadDataFromADC(); newDataNum += mCopyIRAMtoXRAM(&my_buffer[1024] + newDataNum, &ADCData[0], 3); // ch2 ================================ AD_CHS0 = 1; AD_CHS1 = 0; Delay(1); ReadDataFromADC(); newDataNum += mCopyIRAMtoXRAM(&my_buffer[1024] + newDataNum, &ADCData[0], 3); // SendOneByte(DateTime[5]);
}
void main(void) {
uchar idata i = 0; uint idata j = 0, k = 0; ucha
你可以这样,你不需要每次写完数据之后在更新文件长度,你可以多次写完之后在关闭文件,更新文件长度,或者你把数据写完了之后在更新文件长度这样的话速度会快很多,LOCATE命令在数据很多的时候会浪费很长时间。
哦,这样啊,我主要是担心断电啊?
再者,我发现我cpu写数据已经写完了(我有指示灯),可是U盘灯还在不停的闪(标示还在写数据或者读数据),现在文件到了70多MB了,U盘一直不停的闪 。 先前是cpu写数据完了,U盘灯也就 不闪了,下次写再闪。
这样下去如果一个文件到了200MB的话,速度太慢了!
我上面说了,你可以写一个大文件比如写10M之后更新下文件长度在写下一个文件的时候在用LOCATE跳到文件末尾在去打开文件在写10M的数据。往后面写的话,是因为在更新文件的时候时间比较的长。