1、在貴公司提供的U盤互拷程序中,多次用到CH375SaveVariable( )這個(gè)函數(shù),為什么多個(gè)CH375需要用到這個(gè)函數(shù)? 2、參數(shù)mCmdParam.SaveVariable.mSaveVariable分別在什么情況下置0和置1,恢復(fù)變量是什么意思? 3、程序的開頭定義了unsigned char xdata copy_mCmdParam[100],但是卻沒給這倆個(gè)變量賦值,就直接把它賦值mCmdParam.SaveVariable.mBuffer,mCmdParam.SaveVariable.mBuffer=copy_mCmdParam,這一點(diǎn)我不能理解。 下面附上貴公司提供的程序: #define MAX_BYTE_IO 29 /* 以字節(jié)為單位單次讀寫文件時(shí)的最大長(zhǎng)度,默認(rèn)值是29,值大則占用內(nèi)存多,值小則超過(guò)該長(zhǎng)度必須分多次讀寫 */
/* 以下定義的詳細(xì)說(shuō)明請(qǐng)看CH375HF5.H文件 */ #define LIB_CFG_FILE_IO 1 /* 文件讀寫的數(shù)據(jù)的復(fù)制方式,0為"外部子程序",1為"內(nèi)部復(fù)制" */ #define LIB_CFG_INT_EN 0 /* CH375的INT#引腳連接方式,0為"查詢方式",1為"中斷方式" */ /*#define LIB_CFG_UPD_SIZE 1*/ /* 在添加數(shù)據(jù)后是否自動(dòng)更新文件長(zhǎng)度: 0為"不更新",1為"自動(dòng)更新" */ /* 默認(rèn)情況下,如果扇區(qū)數(shù)/字節(jié)數(shù)不為0那么CH375FileWrite/CH375ByteWrite只負(fù)責(zé)寫入數(shù)據(jù)而不修改文件長(zhǎng)度, 如果需要每次寫完數(shù)據(jù)后會(huì)自動(dòng)修改/更新文件長(zhǎng)度,那么可以使全局變量CH375LibConfig的位4為1, 如果長(zhǎng)時(shí)間不寫入數(shù)據(jù)則應(yīng)該更新文件長(zhǎng)度,防止突然斷電后前面寫入的數(shù)據(jù)與文件長(zhǎng)度不相符, 如果確定不會(huì)突然斷電或者后面很快有數(shù)據(jù)不斷寫入則不必更新文件長(zhǎng)度,可以提高速度并減少U盤損耗(U盤內(nèi)部的內(nèi)存壽命有限,不宜頻繁改寫) */ unsigned char volatile xdata CH375_CMD_PORT _at_ 0xAFF1; /* CH375命令端口的I/O地址 */ unsigned char volatile xdata CH375_DAT_PORT _at_ 0xADF0; /* CH375數(shù)據(jù)端口的I/O地址 */ unsigned char volatile xdata CH375_CMD_PORT_U0 _at_ 0x9FF1; /* CH375命令端口的I/O地址 */ unsigned char volatile xdata CH375_DAT_PORT_U0 _at_ 0x9DF0; /* CH375數(shù)據(jù)端口的I/O地址 */ unsigned char Change_Bit; unsigned char xdata copy_buf[512],copy_buf_u0[512]; unsigned char xdata copy_mCmdParam[100],copy_mCmdParam_u0[100]; unsigned char status,status_u0; bit interrupt_bit,interrupt_bit_u0; /* 只使用單片機(jī)內(nèi)置的1KB外部RAM: 0000H-01FFH 為磁盤讀寫緩沖區(qū), 以字節(jié)為單位讀寫文件不需要文件數(shù)據(jù)讀寫緩沖區(qū)FILE_DATA_BUF */ #define DISK_BASE_BUF_ADDR 0x0000 /* 外部RAM的磁盤數(shù)據(jù)緩沖區(qū)的起始地址,從該單元開始的緩沖區(qū)長(zhǎng)度為SECTOR_SIZE */ #define FILE_DATA_BUF_ADDR 0x0200 /* 外部RAM的文件數(shù)據(jù)緩沖區(qū)的起始地址,緩沖區(qū)長(zhǎng)度不小于一次讀寫的數(shù)據(jù)長(zhǎng)度,字節(jié)模式不用該緩沖區(qū) */ /* 由于單片機(jī)內(nèi)置的外部RAM只有1KB, 有些單片機(jī)還要去掉256字節(jié)內(nèi)部RAM, 只剩下768字節(jié)的外部RAM, 其中前512字節(jié)由CH375子程序用于磁盤數(shù)據(jù)緩沖 */ #define FILE_DATA_BUF_LEN 0x4000 /* 外部RAM的文件數(shù)據(jù)緩沖區(qū),緩沖區(qū)長(zhǎng)度不小于一次讀寫的數(shù)據(jù)長(zhǎng)度,字節(jié)模式不用該緩沖區(qū) */
sbit CH375_INT_WIRE = P1^1; /* P1.1, INT0, CH375的中斷線INT#引腳,連接CH375的INT#引腳,用于查詢中斷狀態(tài) */ sbit CH375_INT_WIRE_U0 = P1^2; /* P1.1, INT0, CH375的中斷線INT#引腳,連接CH375的INT#引腳,用于查詢中斷狀態(tài) */
#define NO_DEFAULT_CH375_F_ENUM 1 /* 未調(diào)用CH375FileEnumer程序故禁止以節(jié)約代碼 */ #define NO_DEFAULT_CH375_F_QUERY 1 /* 未調(diào)用CH375FileQuery程序故禁止以節(jié)約代碼 */
#include "CH375HFC.H"
/* 本例用I/O引腳模擬產(chǎn)生CH375的并口讀寫時(shí)序 */ /* 本例中的硬件連接方式如下(實(shí)際應(yīng)用電路可以參照修改下述3個(gè)并口讀寫子程序) */ /* 單片機(jī)的引腳 CH375芯片的引腳 P3.2 INT# P1.0 A0 P1.1 CS# 如果模擬出的并口上只有CH375,那么CS#可以直接接低電平,強(qiáng)制片選 P1.2 WR# P1.3 RD# P0(8位端口) D7-D0 */ //void mDelay1_2uS( ) /* 至少延時(shí)1.2uS,根據(jù)單片機(jī)主頻調(diào)整 */ //{ // return; //}
void CH375_PORT_INIT( ) /* 由于使用通用I/O模塊并口讀寫時(shí)序,所以進(jìn)行初始化 */ { P0 = 0xFF; /* 并口輸入 */ }
void xWriteCH375Cmd( UINT8 mCmd ) /* 外部定義的被CH375程序庫(kù)調(diào)用的子程序,向CH375寫命令 */ { // mDelay1_2uS( ); /* 至少延時(shí)1uS */ if(Change_Bit==0x01) CH375_CMD_PORT=mCmd; else if(Change_Bit==0x02) CH375_CMD_PORT_U0=mCmd; // mDelay1_2uS( ); /* 至少延時(shí)2uS */ }
void xWriteCH375Data( UINT8 mData ) /* 外部定義的被CH375程序庫(kù)調(diào)用的子程序,向CH375寫數(shù)據(jù) */ { if( Change_Bit==0x01) CH375_DAT_PORT=mData; else if(Change_Bit==0x02) CH375_DAT_PORT_U0=mData; // mDelay1_2uS( ); /* 至少延時(shí)1.2uS */ }
UINT8 xReadCH375Data( void ) /* 外部定義的被CH375程序庫(kù)調(diào)用的子程序,從CH375讀數(shù)據(jù) */ { UINT8 mData; // mDelay1_2uS( ); /* 至少延時(shí)1.2uS */ if( Change_Bit==0x01) mData=CH375_DAT_PORT; if( Change_Bit==0x02) mData=CH375_DAT_PORT_U0; return( mData ); }
/* 延時(shí)100毫秒,不精確 */ void mDelay100mS( ) { UINT8 i, j, c; for ( i = 200; i != 0; i -- ) for ( j = 200; j != 0; j -- ) c+=3; }
UINT8 mCopyCodeStringToXRAM( UINT8 xdata *iDestination, UINT8 code *iSource ) { UINT8 i = 0; while ( *iDestination = *iSource ) { iDestination ++; iSource ++; i ++; } return( i ); }
void mCopy_Data_To_Data(unsigned char xdata *data_b0,unsigned char xdata *data_b1,unsigned short len) { unsigned short i; for(i=0;i!=len;i++){ *data_b0=*data_b1; data_b0++; data_b1++; } } /* 檢查操作狀態(tài),如果錯(cuò)誤則顯示錯(cuò)誤代碼并停機(jī) */ void mStopIfError( UINT8 iError ) { if ( iError == ERR_SUCCESS ) return; /* 操作成功 */ printf( "Error: %02X\n", (UINT16)iError ); /* 顯示錯(cuò)誤 */ while ( 1 ) { mDelay100mS( ); mDelay100mS( ); } }
/* 為printf和getkey輸入輸出初始化串口 */ void mInitSTDIO( ) { SCON = 0x50; PCON = 0x80; TMOD = 0x20; TH1 = 0xfe; /* 24MHz晶振, 9600bps */ TR1 = 1; TI = 1; }
void wire_interrupt( )/*檢測(cè)設(shè)備插拔*/ { if(CH375_INT_WIRE==0){ xWriteCH375Cmd(CMD_GET_STATUS); status=xReadCH375Data(); // printf("status=%02x\n",(unsigned short)status); } }
void wire_interrupt_u0( )/*檢測(cè)設(shè)備插拔*/ { if(CH375_INT_WIRE_U0==0){ xWriteCH375Cmd(CMD_GET_STATUS); status_u0=xReadCH375Data(); // printf("status_u0=%02x\n",(unsigned short)status_u0); }
}
main( ) { UINT8 i; UINT32 TotalLen,NewSize; CH375_PORT_INIT( ); /* 由于使用通用I/O模塊并口讀寫時(shí)序,所以進(jìn)行初始化 */ mDelay100mS( ); /* 延時(shí)100毫秒 */ mInitSTDIO( ); /* 為了讓計(jì)算機(jī)通過(guò)串口監(jiān)控演示過(guò)程 */ printf( "Start\n" ); Change_Bit=0x01; i = CH375LibInit( ); /* 初始化CH375程序庫(kù)和CH375芯片,操作成功返回0 */ mStopIfError( i ); Change_Bit=0x02; i = CH375LibInit( ); /* 初始化CH375程序庫(kù)和CH375芯片,操作成功返回0 */ mStopIfError( i ); /* 其它電路初始化 */
while ( 1 ) { // printf( "Wait Udisk\n" ); while(1){ if(interrupt_bit==0){ Change_Bit=0x01; wire_interrupt( ); /* 查詢CH375中斷并更新中斷狀態(tài),等待U盤插入 */ if(status==0x15)interrupt_bit=1; } if(interrupt_bit_u0==0){ Change_Bit=0x02; wire_interrupt_u0( ); if ( status_u0 == 0x15 )interrupt_bit_u0=1; /* 查詢CH375中斷并更新中斷狀態(tài),等待U盤插入 */ } if((interrupt_bit==1)&(interrupt_bit_u0==1))break; } interrupt_bit=0; interrupt_bit_u0=0; mDelay100mS( ); /* 延時(shí),可選操作,有的USB存儲(chǔ)器需要幾十毫秒的延時(shí) */ mDelay100mS( );
/* 檢查U盤是否準(zhǔn)備好,有些U盤不需要這一步,但是某些U盤必須要執(zhí)行這一步才能工作 */ Change_Bit=0x01; for ( i = 0; i < 5; i ++ ) { /* 有的U盤總是返回未準(zhǔn)備好,不過(guò)可以被忽略 */ mDelay100mS( ); // printf( "Ready ?\n" ); if ( CH375DiskReady( ) == ERR_SUCCESS ){ mCmdParam.SaveVariable.mSaveVariable=1; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(copy_buf,DISK_BASE_BUF,0x200); CH375SaveVariable( ); break; /* 查詢磁盤是否準(zhǔn)備好 */ } } Change_Bit=0x02; for ( i = 0; i < 5; i ++ ) { /* 有的U盤總是返回未準(zhǔn)備好,不過(guò)可以被忽略 */ mDelay100mS( ); // printf( "Ready1 ?\n" ); if ( CH375DiskReady( ) == ERR_SUCCESS ) { mCmdParam.SaveVariable.mSaveVariable=1; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(copy_buf_u0,DISK_BASE_BUF,0x200); CH375SaveVariable( ); break; /* 查詢磁盤是否準(zhǔn)備好 */ } } Change_Bit=0x01; mCmdParam.SaveVariable.mSaveVariable=0; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(DISK_BASE_BUF,copy_buf,0x200); CH375SaveVariable( ); CH375DirtyBuffer(); // printf( "Open\n" ); mCopyCodeStringToXRAM( mCmdParam.Open.mPathName, "\\12.TXT" ); /* 文件名,該文件在根目錄下 */ i = CH375FileOpen( ); /* 打開文件 */ if ( i == ERR_SUCCESS ) { /* 文件存在并且已經(jīng)被打開,移動(dòng)文件指針到尾部以便添加數(shù)據(jù) */ mCmdParam.SaveVariable.mSaveVariable=1; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(copy_buf,DISK_BASE_BUF,512); CH375SaveVariable( ); NewSize=CH375vFileSize; TotalLen=(CH375vFileSize+511)>>9; Change_Bit=0x02; mCmdParam.SaveVariable.mSaveVariable=0; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(DISK_BASE_BUF,copy_buf_u0,0x200); CH375SaveVariable( ); CH375DirtyBuffer(); mCopyCodeStringToXRAM( mCmdParam.Open.mPathName, "\\345.TXT" ); /* 文件名,該文件在根目錄下 */ i = CH375FileCreate( ); /* 新建文件并打開,如果文件已經(jīng)存在則先刪除后再新建 */ mStopIfError( i ); mCmdParam.SaveVariable.mSaveVariable=1; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(copy_buf_u0,DISK_BASE_BUF,0x200); CH375SaveVariable(); printf("write\n"); while(1){ printf("TotalLen=%02x\n",(unsigned short)TotalLen); Change_Bit=0x01;//設(shè)備1 mCmdParam.SaveVariable.mSaveVariable=0; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(DISK_BASE_BUF,copy_buf,512); CH375SaveVariable(); CH375DirtyBuffer(); /* printf("a:\n"); for(i=0;i!=100;i++) printf("%02x ",(unsigned short)copy_mCmdParam[i]); printf("\n");*/ mCmdParam.Read.mSectorCount = 32; /* 讀取全部數(shù)據(jù),如果超過(guò)60個(gè)扇區(qū)則只讀取60個(gè)扇區(qū) */ CH375vFileSize += 511; /* 默認(rèn)情況下,以扇區(qū)方式讀取數(shù)據(jù)時(shí),無(wú)法讀出文件尾部不足1個(gè)扇區(qū)的部分,所以必須臨時(shí)加大文件長(zhǎng)度以讀取尾部零頭 */ i = CH375FileRead( ); /* 從文件讀取數(shù)據(jù) */ mStopIfError( i ); CH375vFileSize -= 511; /* 恢復(fù)原文件長(zhǎng)度 */ mCmdParam.SaveVariable.mSaveVariable=1; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(copy_buf,DISK_BASE_BUF,0x200); CH375SaveVariable(); /* printf("b:\n"); for(i=0;i!=100;i++) printf("%02x ",(unsigned short)copy_mCmdParam[i]); printf("\n");*/ Change_Bit=0x02; //設(shè)備2 mCmdParam.SaveVariable.mSaveVariable=0; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(DISK_BASE_BUF,copy_buf_u0,0x200); CH375SaveVariable(); CH375DirtyBuffer(); mCmdParam.Write.mSectorCount = 32; /* 寫入所有扇區(qū)的數(shù)據(jù) */ i = CH375FileWrite( ); /* 向文件寫入數(shù)據(jù) */ mCmdParam.SaveVariable.mSaveVariable=1; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(copy_buf_u0,DISK_BASE_BUF,0x200); CH375SaveVariable(); if(TotalLen<32)break; TotalLen-=32; } Change_Bit=0x02; mCmdParam.SaveVariable.mSaveVariable=0; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(DISK_BASE_BUF,copy_buf_u0,0x200); CH375SaveVariable(); CH375DirtyBuffer(); mCmdParam.Modify.mFileAttr = 0xff; /* 輸入?yún)?shù): 新的文件屬性,為0FFH則不修改 */ mCmdParam.Modify.mFileTime = 0xffff; /* 輸入?yún)?shù): 新的文件時(shí)間,為0FFFFH則不修改,使用新建文件產(chǎn)生的默認(rèn)時(shí)間 */ mCmdParam.Modify.mFileDate = MAKE_FILE_DATE( 2004, 5, 18 ); /* 輸入?yún)?shù): 新的文件日期: 2004.05.18 */ mCmdParam.Modify.mFileSize = NewSize; /* 輸入?yún)?shù): 如果原文件較小,那么新的文件長(zhǎng)度與原文件一樣長(zhǎng),否則被RAM所限,如果文件長(zhǎng)度大于64KB,那么NewSize必須為UINT32 */ i = CH375FileModify( ); /* 修改當(dāng)前文件的信息,修改日期和長(zhǎng)度 */ mStopIfError( i ); mCmdParam.Close.mUpdateLen = 0; /* 不要自動(dòng)計(jì)算文件長(zhǎng)度,如果自動(dòng)計(jì)算,那么該長(zhǎng)度總是512的倍數(shù) */ i = CH375FileClose( ); printf("close\n"); mStopIfError( i ); Change_Bit=0x01; mCmdParam.SaveVariable.mSaveVariable=0; //為0時(shí)恢復(fù)變量,為1時(shí)保存變量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的緩沖區(qū) // mCopy_Data_To_Data(DISK_BASE_BUF,copy_buf,0x200); CH375SaveVariable(); CH375DirtyBuffer(); mCmdParam.Close.mUpdateLen = 0; /* 不要自動(dòng)計(jì)算文件長(zhǎng)度,如果自動(dòng)計(jì)算,那么該長(zhǎng)度總是512的倍數(shù) */ i = CH375FileClose( ); mStopIfError( i ); } while(1){ if(interrupt_bit==0){ Change_Bit=0x01; wire_interrupt( ); /* 查詢CH375中斷并更新中斷狀態(tài),等待U盤插入 */ if(status==0x16)interrupt_bit=1; } if(interrupt_bit_u0==0){ Change_Bit=0x02; wire_interrupt_u0( ); if ( status_u0 == 0x16 )interrupt_bit_u0=1; /* 查詢CH375中斷并更新中斷狀態(tài),等待U盤插入 */ } if((interrupt_bit==1)||(interrupt_bit_u0==1)){ if(interrupt_bit==1) interrupt_bit=0; if(interrupt_bit_u0==1) interrupt_bit_u0=0; break; } } printf("again\n"); // while ( CH375DiskStatus != DISK_DISCONNECT ) xQueryInterrupt( ); /* 查詢CH375中斷并更新中斷狀態(tài),等待U盤拔出 */ mDelay100mS( ); mDelay100mS( ); } }