我写了一个测试板数据传输测试软件,工作过程如下: 主程序调用mDownloadData函数向单片机写一组数据,单片机收到数据后, 向端口对数据处理,发出中断,通知上位机读取处理过的数据 发送数据是使用DEF_CMD_DOWN_DATA命令 上位机程序片断如下: //-------------------------------------------------------------- // 中断服务程序是由CH375驱动程序中断后通过DLL在应用层模拟调用的 VOID CALLBACK mInterruptEvent( PUCHAR iBuffer ) { UINT iKeyCode; CString csWindow = "UsbTest"; HWND hWnd = ::FindWindowEx(NULL,NULL,NULL,csWindow); if ( IsWindow(hWnd) ) {// CH375产生中断后,产生一个消息通知主程序 if ( iBuffer[0] == 1 ) // 检查中断特征数据 { //.... } else { if ( iBuffer[0] == 2 ) { //... } else { // 中断特征数据为3,表明有上传数据 if ( iBuffer[0] == 3 ) // 检查中断特征数据 { PostMessage( hWnd, IDC_INT_READ, iBuffer[0] ,iKeyCode); } } } }

} LONG CUsbTestDlg::OnRead(UINT wParam,LONG lParam) { mCOMMAND_PACKET mDemoReq; ULONG i,nLength; UCHAR iBuffer[4096];

wParam = 32; if ( wParam > 4096 ) { AfxMessageBox("单次上传数据长度超过4096字节"); return( FALSE ); } nLength = wParam; if ( CH375ReadData( mIndex, iBuffer, &nLength ) ) // 通过CH375接收数据,成功 { return( nLength ); } else AfxMessageBox("CH375ReadData 上传数据失败");

return( 0 ); } UINT CUsbTestDlg::mDownloadData( UCHAR *iBuffer, UINT iLength ) { mCOMMAND_PACKET mDemoReq; ULONG mLength;

if ( iLength > 4096 ) { AfxMessageBox( "单次下传数据长度超过4096字节"); return( FALSE ); } mDemoReq.mCommandCode = DEF_CMD_DOWN_DATA; // 连续下传数据块 mDemoReq.mCommandCodeNot = ~ DEF_CMD_DOWN_DATA; mDemoReq.mBufferID = ACCESS_MCS51_XRAM; mDemoReq.mBufferAddr = 0x8200; mDemoReq.mLength = iLength; // 传输数据总长度 mLength = CONST_CMD_LEN; // 命令包的长度 if ( CH375WriteData( mIndex, &mDemoReq, &mLength ) ) // 通过CH375发送命令包,成功 { mLength = iLength; if ( ( mLength % 64 ) == CONST_CMD_LEN ) mLength ++; if ( CH375WriteData( mIndex, iBuffer, &mLength ) ) ; else { AfxMessageBox("CH375WriteData 下传数据失败"); mLength = 0; } } else { AfxMessageBox("CH375WriteData 发送命令失败,DEF_CMD_DOWN_DATA"); mLength = 0; }

return( mLength ); } //--------------------------------------- 下位机程序片断如下: / /* 上传中断数据子程序(通过中断端点上传),可选子程序 */ void LoadIntData( unsigned char c1, unsigned char c2 ) { unsigned int i; for ( i=1000; i!=0; i-- ) { /* 等待发送中断数据完成,因为PC机每隔1毫秒就读取中断数据,所以最多等待1毫秒 */ if ( FLAG_INT_WAIT == 0 ) break; /* 前次中断数据已经被PC机取走 */ } /* 如果未与计算机相连,或者计算机中的应用程序未运行,则会出现超时,否则不超过1毫秒中断数据就应该被PC机取走 */ EX0 = 0; /* 为了防止中途被中断而乱了顺序,必须先禁止中断 */ CH375_CMD_PORT = CMD_WR_USB_DATA5; /* 向USB端点1的发送缓冲区写入数据块 */ Delay2us( ); CH375_DAT_PORT = 2; /* 后续数据长度 */ /* 虽然每次可以上传8个字节, 但是本程序中用于键盘中断, 所以每次只需要传输两个字节 */ FLAG_INT_WAIT = 1; /* 置中断等待标志 */ CH375_DAT_PORT = c1; /* 发送中断数据1 */ CH375_DAT_PORT = c2; /* 发送中断数据2 */ EX0 = 1; /* 允许中断 */ }

/* CH375中断服务程序INT0,使用寄存器组1 */ void mCH375Interrupt( ) interrupt 0 using 1 {

CH375_CMD_PORT = CMD_GET_STATUS; /* 获取中断状态并取消中断请求 */ Delay2us( ); /* 如果时钟频率低于16MHz则无需该指令延时 */ InterruptStatus = CH375_DAT_PORT; /* 获取中断状态 */ IE0 = 0; /* 清中断标志,对应于INT0中断 */ if ( InterruptStatus == USB_INT_EP2_OUT ) { /* 批量端点下传成功 */ CH375_CMD_PORT = CMD_RD_USB_DATA; Delay2us( ); /* 如果时钟频率低于16MHz则无需该指令延时 */ length = CH375_DAT_PORT; /* 首先读取后续数据长度 */ if ( length == CONST_CMD_LEN ) { /* 命令块长度总是CONST_CMD_LEN,分析并处理命令 */ for ( i=0; i if ( CMD_PKT.mCommandCode != (unsigned char)( ~ CMD_PKT.mCommandCodeNot ) ) return; switch ( CMD_PKT.mCommandCode ) { case DEF_CMD_GET_INFORM: break; case DEF_CMD_TEST_DATA:

break; case DEF_CMD_CLEAR_UP: break; case DEF_CMD_UP_DATA:

break; case DEF_CMD_DOWN_DATA:

break; default: break; } } else if ( length == 0 ) return; else { if ( CMD_PKT.mCommandCode == DEF_CMD_DOWN_DATA ) {

CurrentRamLen -= length; while ( length-- ) { *CurrentRamAddr = CH375_DAT_PORT; CurrentRamAddr ++; } /********************************************************* 我添加的代码 **********************************************************/ LoadUpData( InformString1, 32 ); LoadIntData(1, 127 ); /***********************************************************/ } else { /* 未定义的命令 */ while ( length -- ) c1 = CH375_DAT_PORT; /* 丢弃数据 */ } } } else if ( InterruptStatus == USB_INT_EP2_IN ) { }

} else if ( InterruptStatus == USB_INT_EP1_IN ) { } else { /* 内置固件的USB方式下不应该出现其它中断状态 */ } }