我用CH375采集數據然后寫進U盤。I/O引腳模擬8位并行總線讀寫,庫是“CH375HF5.H” 字節(jié)讀寫的方式。大致的流程是:先用CH375FileCreate創(chuàng)建一個文件(文件名是可以變的),然后我有一個定時中斷,差不多每隔3秒向這個文件寫64B數據(用的是 ByteWrite),若干次后用CH375FileClose關閉文件,在關閉之前 mCmdParam.Close.mUpdateLen = 1; 更新長度。 還有U盤是格式化成FAT16的形式。 現在遇到的問題是: 問題1:經常寫完文件在計算機上打不開,用磁盤工具看了一下,文件長度、時間等都正確 但初始簇的位置不對。比如,文件長是180字節(jié),位于02簇,但在FAT表里,該目錄項的最后 是:…………02 00 XX B4 00 00 00,就是說多了個XX(XX是一個隨意的16進制數)使得文 件的初始簇變成了XX00(本來應該是0002),所以文件肯定是打不開的。 問題2:當創(chuàng)建第二個文件的時候,該目錄項不是寫了一個新的32字節(jié),而是從上一個目錄 項的最后一個字節(jié)開始寫。如上例,變成了…………02 00 B4 00 00 YY(YY是新文件名第一個字符的ASCII碼)這樣,原有的第一個文件長度肯定是不對了(變成了YY0000B4), 而新文件所有的目錄項內容都往前錯了一個字節(jié),所以全部不對了。 問題3:在定時中斷中用字節(jié)方式往文件里寫數據,但不是每次都能寫成功,常出現的錯誤 有1F等,且有一定的隨機性。 請教這三個問題是什么原因造成的?怎樣解決,謝謝!
應該是I/O模擬時序有問題,導致數據字節(jié)錯位或者錯誤,貼出來看看吧
多謝,將延時加長了一些,問題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 )// 檢查操作狀態(tài) { 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中斷, 在字節(jié)方式寫數據進文件 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字節(jié) //mIndex是緩沖區(qū)中數據的索引 //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字節(jié)寫一次U盤,每中斷一次得到4字節(jié),16秒64字節(jié) if (mIndex==64) { mIndex=0; mCmdParam.ByteWrite.mByteCount = 64; i = CH375ByteWrite( ); mStopIfError( i ); //自動更新長度,加不加好像區(qū)別不大 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盤創(chuàng)建文件有關 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試一下
最后的問題,我有些不太明白,都是字節(jié)讀寫,文本都可以,數據有什么不可以的呢
文本內容是ASCII字符,數據內容有非ASCII字符,以文件方式操做就出錯。 這么說對不對?
[Emot]7[/Emot]
數據文件肯定是非ASCII字符的,問題是我并不是用記事本之類的去打開它,而是想把它從U盤拷到硬盤,這個應該和文件的格式內容無關的吧? 請教Johnny.Yang, HF6支持IO引腳直接讀寫的方式嗎?謝謝!
剛才又試了一下,文本方式也不行。就是說用磁盤工具看文件是正常的,但是想在計算機上打開或者拷貝文件就是不行。想了一下,問題不是由于字節(jié)方式造成的,如果我用字節(jié)方式一氣把文件寫完就沒問題。問題出在我是在定時中斷里每隔一秒寫一次文件,造成的,但是是什么原因?請教各位。
找到問題了,如果文件名是固定不變的話就完全正常了。但是我需要創(chuàng)建多個文件,怎么辦呢?
兩個問題, 一是模擬I/O時序可能會有問題,感覺你程序太慢,如果CPU較快那么P0端口可能要加上拉, 嚴格參考MCS51/FILELIB7/EXAM7中的,只需要調整延時子程序 二是文件名,Samp_000.EGG不行,必須全用大寫字母SAMP_000.EGG, 否則文件看起來存在,但文件打不開、復制不了
修改好程序后,先重新格式化U盤(之前試驗導致U盤數據有誤)再試驗,確保你沒問題
找到問題了,是AD采樣時間過長造成的,采4次的時間已經超過1秒了,所以中斷不可靠。 文件名都改為大寫后還是偶爾會出錯,索性把文件名固定了,而且數據都改成了文本格式,現在用起來還不錯 謝謝!