我看的例子里都是只讀前600個字符,然后自已修改了一下,但用扇區(qū)讀時總是讀不出最后一個扇區(qū)的文件.
扇區(qū)讀之前,需要對文件長度CH375vFileSize作特殊處理: CH375vFileSize += CH375vSectorSize - 1; i = CH375FileRead(); CH375vFileSize -= CH375vSectorSize - 1; 如果實際讀取的扇區(qū)數(shù)小于需要讀取的扇區(qū)數(shù),則表示文件結(jié)束
謝謝SCM!不過我沒完全理解你的意思。
我是這樣做的: SecCount=(CH375vFileSize+511)>>9 ;//先算出文件有多少扇區(qū) 然后用循環(huán) for (number=0; number<=SecCount; number++) //讀出全部扇區(qū)(每次讀一個扇區(qū))
這樣讀時最后一個扇區(qū)讀不出來,而且現(xiàn)在還有個疑問:如果最后一個扇區(qū)沒有512個字節(jié),那我怎么判斷它結(jié)束呢?
(1)扇區(qū)計算:SecCount = ( CH375vFileSize + CH375vSectorSize - 1 ) / CH375vSectorSize,并非所有U盤扇區(qū)均為512 (2)CH375vFileSize需按1樓作特殊處理,才能讀出最后一個扇區(qū) (3)按上述處理后,文件尾零頭數(shù)據(jù)肯定是滿一個扇區(qū)大小的;讀之后,如果mCmdParam.Read.mSectorCount小于需要讀取的扇區(qū)數(shù),則表示文件結(jié)束 上述三點,我們的示例程序中均有注釋
void main() { UINT8 i,c,SecCount ; UINT16 NewSize,count,number ; UINT8*pCodeStr ; CH375_PORT_INIT(); LED_OUT_INIT(); LED_OUT_ACT(); /* 開機(jī)后LED亮一下以示工作 */ mDelaymS(100); /* 延時100毫秒 */ LED_OUT_INACT(); mInitSTDIO(); /* 為了讓計算機(jī)通過串口監(jiān)控演示過程 */ printf("Start\n"); i=CH375LibInit(); /* 初始化CH375程序庫和CH375芯片,操作成功返回0 */ mStopIfError(i); /* 其它電路初始化 */ while(1) { printf("Wait Udisk\n"); while(CH375DiskStatus!=DISK_CONNECT) xQueryInterrupt(); /* 查詢CH375中斷并更新中斷狀態(tài),等待U盤插入 */ LED_OUT_ACT(); /* LED亮 */ mDelaymS(200); /* 延時,可選操作,有的USB存儲器需要幾十毫秒的延時 */ /* 檢查U盤是否準(zhǔn)備好,有些U盤不需要這一步,但是某些U盤必須要執(zhí)行這一步才能工作 */ for(i=0;i<5;i++) { /* 有的U盤總是返回未準(zhǔn)備好,不過可以被忽略 */ mDelaymS(100); printf("Ready ?\n"); if(CH375DiskReady()==ERR_SUCCESS)break ; /* 查詢磁盤是否準(zhǔn)備好 */ } /* 查詢磁盤物理容量 */ /* printf( "DiskSize\n" ); i = CH375DiskSize( ); mStopIfError( i ); printf( "TotalSize = %d MB \n", (unsigned int)( mCmdParam.DiskSize.mDiskSizeSec >> 11 ) ); 顯示為以MB為單位的容量 */ /* 讀取原文件 */ printf("Open\n"); strcpy((char*)mCmdParam.Open.mPathName,"/STEVEN.C"); /* 文件名,該文件在C51子目錄下 */ i=CH375FileOpen(); /* 打開文件 */ if(i==ERR_MISS_DIR||i==ERR_MISS_FILE) { printf("\\C51\\CH375HFT.C can't found\r\n"); } else { /* 找到文件或者出錯 */ mStopIfError(i); /* printf( "Query\n" ); i = CH375FileQuery( ); //查詢當(dāng)前文件的信息 mStopIfError( i ); */ printf("Read\n"); printf("CH375vFileSize = %lu\n",CH375vFileSize); if(CH375vFileSize < FILE_DATA_BUF_LEN) { SecCount=1 ; //如果文件小于一個扇區(qū)則讀一個扇區(qū) //NewSize=FILE_DATA_BUF_LEN ; } else { //* 如果原文件較大,那么使用原長度 SecCount=(CH375vFileSize+511)>>9 ; //* (CH375vFileSize+511)/512, 計算文件的扇區(qū)數(shù),因為讀寫是以扇區(qū)為單位的,先加511是為了讀出文件尾部不足1個扇區(qū)的部分 //NewSize=(UINT16)CH375vFileSize ; } //如果文件比較大,一次讀不完,可以再調(diào)用CH375FileRead繼續(xù)讀取,文件指針自動向后移動 printf("START READ FILE\n"); printf("SecCount = %u\n",SecCount); PORTC=0x00 ; //for(number=0;number while(1) { c=1 ; //每次讀取32個扇區(qū) mCmdParam.Read.mSectorCount=1 ; //指定讀取的扇區(qū)數(shù) CH375FileRead(); //讀完后文件指針自動后移 //處理數(shù)據(jù) for(count=0;count<512;count++) { printf("%c",FILE_DATA_BUF[count]); } if ( mCmdParam.Read.mSectorCount < c ) break; //實際讀出的扇區(qū)數(shù)較小則說明文件已經(jīng)結(jié)束 } PORTC=0xFF ; printf("\nEND OF FILE\n");
printf("Close\n"); i=CH375FileClose(); /* 關(guān)閉文件 */ mStopIfError(i); printf("Take out\n"); while(CH375DiskStatus!=DISK_DISCONNECT)xQueryInterrupt(); /* 查詢CH375中斷并更新中斷狀態(tài),等待U盤拔出 */ LED_OUT_INACT(); /* LED滅 */ mDelaymS(200); } } }
這是我修改的程序,請幫忙看看是哪出了問題,謝謝!
CH375vFileSize += CH375vSectorSize - 1; while(1) { c=1 //每次讀取32個扇區(qū) mCmdParam.Read.mSectorCount=1 //指定讀取的扇區(qū)數(shù) CH375FileRead(); //讀完后文件指針自動后移 //處理數(shù)據(jù) for(count=0;count<512;count++) { printf("%c",FILE_DATA_BUF[count]); } if ( mCmdParam.Read.mSectorCount < c ) break; //實際讀出的扇區(qū)數(shù)較小則說明文件已經(jīng)結(jié)束 } CH375vFileSize -= CH375vSectorSize - 1;
按扇區(qū)讀寫方式中是不去處理最后的不足一個扇區(qū)的數(shù)據(jù),例如你有3個扇區(qū)+33字節(jié)的文件,如果你不將原來的文件長度+CH375vSectorSize-1的話,那么第4個扇區(qū)的數(shù)據(jù)就會丟掉.當(dāng)你將文件長度增加CH375vSectorSize-1之后,文件就的長度變成4個整扇區(qū)+33字節(jié)(當(dāng)然,文件的實際數(shù)據(jù)沒有變化),自然也就可以讀取出最后的數(shù)據(jù)了.至于程序的修改處,樓上已經(jīng)給出.
補充下:按照SCM給出的修改后 //* 如果原文件較大,那么使用原長度 SecCount=(CH375vFileSize+511)>>9 //這里不需要再加511 //NewSize=(UINT16)CH375vFileSize
謝謝兩位,終于可以讀到文件結(jié)束了.不過還有點小問題 if ( mCmdParam.Read.mSectorCount < c ) break; 這句要放到處理數(shù)據(jù)的前面,要不然會處理兩次,呵呵 還有一個問題:因為最后讀出的不是一整個扇區(qū)都有內(nèi)容,那么我怎么知道到底有幾個是有效的呢?
而且我還是沒弄明白我這樣做為什么不對: for(number=0;number //CH375vFileSize += 511; //while(1) { c=1 ; //每次讀取32個扇區(qū) mCmdParam.Read.mSectorCount=1 ; //指定讀取的扇區(qū)數(shù) CH375FileRead(); //讀完后文件指針自動后移 //處理數(shù)據(jù) //if ( mCmdParam.Read.mSectorCount < c ) break; //實際讀出的扇區(qū)數(shù)較小則說明文件已經(jīng)結(jié)束 for(count=0;count<512;count++) { printf("%c",FILE_DATA_BUF[count]); } }
這個可以不去關(guān)心,當(dāng)程序中增加長度只是為了去讀最后的數(shù)據(jù)。當(dāng)讀到文件結(jié)束時停止,不會再繼續(xù)讀取,不會有無效的數(shù)據(jù)被讀出.
你原來的程序中: if(CH375vFileSize < FILE_DATA_BUF_LEN) {//這里需要加上CH375vFileSize+=CH375vSectorSize-1; SecCount=1 //如果文件小于一個扇區(qū)則讀一個扇區(qū) //NewSize=FILE_DATA_BUF_LEN } 改動后,你再用你的程序試一試.讀取結(jié)束后,不要忘了CH375vFileSize-=CH375vSectorSize-1
謝謝m4,我把 CH375vFileSize += 511;這句加到for的前面OK了,但我沒想明白它有什么用.感覺我已經(jīng)算出了文件占多少扇區(qū),然后讀這么多扇區(qū)就應(yīng)該可以了,跟文件長度應(yīng)該沒關(guān)才對呀.
實際計算的時候,你是根據(jù)CH375vFileSize來計算扇區(qū)數(shù),當(dāng)你的CH375vFileSize=1的時候的話,那么你計算的扇區(qū)數(shù)就為0,這樣在你讀取的話,你發(fā)送的扇區(qū)數(shù)就為0,讀取不到數(shù)據(jù).而你CH375vFileSize+=511的話,那么你計算的時候,文件扇區(qū)數(shù)就會為1,這樣你按照扇區(qū)來讀的話就能讀取到數(shù)據(jù)了.
我們有個說明文檔CH375HF.PDF你可以去看,里面有相關(guān)函數(shù)的詳細(xì)的說明。