两个ch375,一片单片机控制,每一片ch375单独调试U盘读写都成功。 按照论坛里的U盘对拷程序例程,稍作改动对应好硬件连接,程序不能正常运行, 我pcb上有些led灯对应程序的运行,对拷程序一插上第二个u盘程序不能正常往下走,按照led提示好像从头运行不停循环,求助是什么原因
main( ) { UINT8 i; UINT32 TotalLen,NewSize;
_8155_CMD=0x4f; _8155_A =0xff;
LED_OUT_INIT( ); LED_OUT_ACT( ); /* 开机后LED亮一下以示工作 */ mDelay100mS( ); /* 延时100毫秒 */ LED_OUT_INACT( );
CH375_PORT_INIT( ); /* 由于使用通用I/O模块并口读写时序,所以进行初始化 */ mDelay100mS( ); /* 延时100毫秒 */
Change_Bit=0x01; i = CH375LibInit( ); /* 初始化CH375程序库和CH375芯片,操作成功返回0 */ mStopIfError( i ); Change_Bit=0x02; i = CH375LibInit( ); /* 初始化CH375程序库和CH375芯片,操作成功返回0 */ mStopIfError( i ); /* 其它电路初始化 */ interrupt_bit=0; interrupt_bit_u0=0; while ( 1 ) { LED4_ACT( ); while((interrupt_bit==0)||(interrupt_bit_u0==0)){ if(interrupt_bit==0){ Change_Bit=0x01; wire_interrupt( ); /* 查询CH375中断并更新中断状态,等待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中断并更新中断状态,等待U盘插入 */ } } interrupt_bit=0; interrupt_bit_u0=0; mDelay100mS( ); /* 延时,可选操作,有的USB存储器需要几十毫秒的延时 */ mDelay100mS( ); LED4_INACT( ); /* 检查U盘是否准备好,有些U盘不需要这一步,但是某些U盘必须要执行这一步才能工作 */ Change_Bit=0x01; for ( i = 0; i < 5; i ++ ) { /* 有的U盘总是返回未准备好,不过可以被忽略 */ mDelay100mS( );
if ( CH375DiskReady( ) == ERR_SUCCESS ){ mCmdParam.SaveVariable.mSaveVariable=1; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的缓冲区
CH375SaveVariable( ); break; /* 查询磁盘是否准备好 */ } } Change_Bit=0x02; for ( i = 0; i < 5; i ++ ) { /* 有的U盘总是返回未准备好,不过可以被忽略 */ mDelay100mS( );
if ( CH375DiskReady( ) == ERR_SUCCESS ) { mCmdParam.SaveVariable.mSaveVariable=1; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的缓冲区
CH375SaveVariable( ); break; /* 查询磁盘是否准备好 */ } }
Change_Bit=0x01; mCmdParam.SaveVariable.mSaveVariable=0; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的缓冲区
CH375SaveVariable( ); CH375DirtyBuffer();
LED_RUN_ACT( ); /* 开始操作U盘 */
mCopyCodeStringToXRAM( mCmdParam.Open.mPathName, "/NEWFILE1.TXT" ); /* 文件名,该文件在根目录下 */ i = CH375FileOpen( ); /* 打开文件 */
if ( i == ERR_MISS_DIR || i == ERR_MISS_FILE ) { LED_RUN_INACT( ); break; } else { /* 找到文件或者出错 */ mStopIfError( i );
mCmdParam.SaveVariable.mSaveVariable=1; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的缓冲区 CH375SaveVariable();
NewSize=1048576; TotalLen=(NewSize+511)>>9;
Change_Bit=0x02; mCmdParam.SaveVariable.mSaveVariable=0; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的缓冲区 CH375SaveVariable();
CH375DirtyBuffer();
mCopyCodeStringToXRAM( mCmdParam.Open.mPathName, "/NEWFILE3.TXT"); /* 文件名,该文件在根目录下 */ i = CH375FileCreate( ); /* 新建文件并打开,如果文件已经存在则先删除后再新建 */ if ( i == ERR_MISS_DIR || i == ERR_MISS_FILE ) {i = CH375FileCreate( ); } mStopIfError( i );
mCmdParam.SaveVariable.mSaveVariable=1; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的缓冲区 CH375SaveVariable();
while(1){ LED_WR_ACT( ); /* 写操作 */ Change_Bit=0x01;//设备1 mCmdParam.SaveVariable.mSaveVariable=0; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的缓冲区
CH375SaveVariable(); CH375DirtyBuffer();
mCmdParam.Read.mSectorCount = 32; /* 读取全部数据,如果超过60个扇区则只读取60个扇区 */ CH375vFileSize += 511; /* 默认情况下,以扇区方式读取数据时,无法读出文件尾部不足1个扇区的部分,所以必须临时加大文件长度以读取尾部零头 */ i = CH375FileRead( ); /* 从文件读取数据 */ mStopIfError( i ); CH375vFileSize -= 511; /* 恢复原文件长度 */
mCmdParam.SaveVariable.mSaveVariable=1; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的缓冲区
CH375SaveVariable();
Change_Bit=0x02; //设备2 mCmdParam.SaveVariable.mSaveVariable=0; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的缓冲区
CH375SaveVariable(); CH375DirtyBuffer(); mCmdParam.Write.mSectorCount = 32; /* 写入所有扇区的数据 */ i = CH375FileWrite( ); /* 向文件写入数据 */
mCmdParam.SaveVariable.mSaveVariable=1; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的缓冲区
CH375SaveVariable();
LED_WR_INACT( ); if(TotalLen<32)break; TotalLen-=32; } Change_Bit=0x02; mCmdParam.SaveVariable.mSaveVariable=0; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的缓冲区
CH375SaveVariable(); CH375DirtyBuffer(); mCmdParam.Modify.mFileAttr = 0xff; /* 输入参数: 新的文件属性,为0FFH则不修改 */ mCmdParam.Modify.mFileTime = 0xffff; /* 输入参数: 新的文件时间,为0FFFFH则不修改,使用新建文件产生的默认时间 */ mCmdParam.Modify.mFileDate = MAKE_FILE_DATE( 2004, 5, 18 ); /* 输入参数: 新的文件日期: 2004.05.18 */ mCmdParam.Modify.mFileSize = NewSize; /* 输入参数: 如果原文件较小,那么新的文件长度与原文件一样长,否则被RAM所限,如果文件长度大于64KB,那么NewSize必须为UINT32 */ i = CH375FileModify( ); /* 修改当前文件的信息,修改日期和长度 */ mStopIfError( i ); mCmdParam.Close.mUpdateLen = 0; /* 不要自动计算文件长度,如果自动计算,那么该长度总是512的倍数 */ i = CH375FileClose( );
mStopIfError( i ); Change_Bit=0x01; mCmdParam.SaveVariable.mSaveVariable=0; //为0时恢复变量,为1时保存变量 mCmdParam.SaveVariable.mBuffer=copy_mCmdParam; //指向要保存的缓冲区
CH375SaveVariable(); CH375DirtyBuffer(); mCmdParam.Close.mUpdateLen = 0; /* 不要自动计算文件长度,如果自动计算,那么该长度总是512的倍数 */ i = CH375FileClose( ); mStopIfError( i ); }
LED_RUN_INACT( );
while(1){ if(interrupt_bit==0){ Change_Bit=0x01; wire_interrupt( ); /* 查询CH375中断并更新中断状态,等待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中断并更新中断状态,等待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; } }
LED_OUT_INACT( ); /* LED灭 */ LED_RUN_INACT( ); LED_WR_INACT( ); // while ( CH375DiskStatus != DISK_DISCONNECT ) xQueryInterrupt( ); /* 查询CH375中断并更新中断状态,等待U盘拔出 */ mDelay100mS( ); mDelay100mS( ); } }
好像是 CH375SaveVariable(); 这种函数回导致不正常
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;
#define DISK_BASE_BUF_ADDR 0x0000 /* 外部RAM的磁盘数据缓冲区的起始地址,从该单元开始的缓冲区长度为SECTOR_SIZE */ #define FILE_DATA_BUF_ADDR 0x0200 #define FILE_DATA_BUF_LEN 0x4000 /* 外部RAM的文件数据缓冲区,缓冲区长度不小于一次读写的数据长度,字节模式不用该缓冲区 */
这样的变量定义正确吗?比如unsigned char xdata copy_mCmdParam[100], 这种用到外部ram的定义会和外部RAM的文件数据缓冲区冲突吗?
请问unsigned char xdata copy_buf[512],copy_buf_u0[512]; 这两个数组哪里用到?CH375SaveVariable(); 是这个函数吗?问题是不是出在这里呢?
帮忙看一下这几句汇编,是不是有问题呢?mCmdParam.SaveVariable.mSaveVariable好像应该不是xdata吧,怎么用了movx?
292: mCmdParam.SaveVariable.mSaveVariable=0; //为0时恢复变量,为1时保存变量 C:0x0E8C E4 CLR A C:0x0E8D 9006C8 MOV DPTR,#mCmdParam(0x06C8) C:0x0E90 F0 MOVX @DPTR,A 293: mCmdParam.SaveVariable.mBuffer=copy_mCmdParam_u0; //指向要保存的缓冲区 C:0x0E91 9006CC MOV DPTR,#0x06CC C:0x0E94 7402 MOV A,#0x02 C:0x0E96 F0 MOVX @DPTR,A C:0x0E97 A3 INC DPTR C:0x0E98 7464 MOV A,#0x64 C:0x0E9A F0 MOVX @DPTR,A 294: CH375SaveVariable();
1、先不要做对考,验证单个U盘的读写能否成功,通过后再作对考,否则不知道哪一路有问题 2、mCmdParam是定义在XDATA的,它是一个结构体变量,以它为准
单个u盘读写没问题,不过没用到CH375SaveVariable这样的函数,两个ch375都调试过了,扇区读写都没问题
现在问题是哪一路单独调试都没问题,排除ch375部分的硬件问题,对考程序看起来也没问题,执行不正常,似乎一到CH375SaveVariable就乱了
LibInit、DiskConnect、DiskReady、FileOpen、文件读写,其中哪一步出错了,错误代码是多少?
我没接串口调试,不过从指示灯情况来看,初始化没问题,插入第二个u盘后就会乱掉,我把查询磁盘是否准备好 的程序段删掉程序还是会乱掉,这样来看似乎就是一执行到CH375SaveVariable这样的函数就会出问题
单用指示灯,只能看个大概,必须能够监视库函数的返回值,才能知道除了什么错误,想办法用串口监视程序的流程
在ch375hfc.h这个头文件里,UINT8 mSaveVariable 这不是定义在片内吗?
另外 UINT8 mCopyCodeStringToXRAM( UINT8 xdata *iDestination, UINT8 code *iSource ) 为什么是XRAM? mCopyCodeStringToXRAM( mCmdParam.Open.mPathName, "\\12.TXT" ); 但是在ch375hfc.h里面,UINT8 mPathName[ MAX_PATH_LEN ]; 这个不是在片内吗?
我在单独调一个u盘时,用到的例程都是UINT8 mCopyCodeStringToIRAM ,不是XRAM,都成功了,到这个对拷程序怎么变成片外了
mPathName是结构的成员,至于类型,要看结构体变量mCmdParam是怎么定义的 还是想办法监控下问题出在哪一步
我把程序精简到只剩查询插入u盘和检查是否准备好,问题出现在检查U盘是否准备好这一步,(去掉这不程序正常),是不是在同时插入两个u盘以后,执行DiskReady单片机不知道指向那一片ch375?但是前面的初始化都正常跑过了。 main( ) { UINT8 i; UINT32 TotalLen,NewSize;
_8155_CMD=0x4f; _8155_A =0xff;
LED_OUT_INIT( ); LED_OUT_ACT( ); /* 开机后LED亮一下以示工作 */ mDelay100mS( ); /* 延时100毫秒 */ LED_OUT_INACT( );
CH375_PORT_INIT( ); /* 由于使用通用I/O模块并口读写时序,所以进行初始化 */ mDelay100mS( ); /* 延时100毫秒 */
Change_Bit=0x01; i = CH375LibInit( ); /* 初始化CH375程序库和CH375芯片,操作成功返回0 */ mStopIfError( i ); Change_Bit=0x02; i = CH375LibInit( ); /* 初始化CH375程序库和CH375芯片,操作成功返回0 */ mStopIfError( i ); /* 其它电路初始化 */ interrupt_bit=0; interrupt_bit_u0=0; while ( 1 ) { LED4_ACT( ); while((interrupt_bit==0)||(interrupt_bit_u0==0)){ if(interrupt_bit==0){ Change_Bit=0x01; wire_interrupt( ); /* 查询CH375中断并更新中断状态,等待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中断并更新中断状态,等待U盘插入 */ } } interrupt_bit=0; interrupt_bit_u0=0; mDelay100mS( ); /* 延时,可选操作,有的USB存储器需要几十毫秒的延时 */ mDelay100mS( ); LED4_INACT( ); /* 检查U盘是否准备好,有些U盘不需要这一步,但是某些U盘必须要执行这一步才能工作 */
Change_Bit=0x01; for ( i = 0; i < 5; i ++ ) { /* 有的U盘总是返回未准备好,不过可以被忽略 */ mDelay100mS( );
if ( CH375DiskReady( ) == ERR_SUCCESS ){ break; /* 查询磁盘是否准备好 */ } }
LED_RUN_ACT( ); /* 开始操作U盘 */
while(1){ if(interrupt_bit==0){ Change_Bit=0x01; wire_interrupt( ); /* 查询CH375中断并更新中断状态,等待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中断并更新中断状态,等待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; } }
LED_OUT_INACT( ); /* LED灭 */ LED_RUN_INACT( ); LED_WR_INACT( );
mDelay100mS( ); mDelay100mS( ); } }
麻烦看一下程序,去掉检查u盘那一段正常,插入两个u盘,然后拔出任何一个u盘程序循环 现在这段程序里,问题就出在DiskReady这个函数