請(qǐng)教一下,目前用CH374U鏈接USBmidi后發(fā)現(xiàn)有丟包現(xiàn)象,具體情況就是鋼琴琴鍵按下或者放手的時(shí)候,有時(shí)候獲取不到這包數(shù)據(jù),我在midi鋼琴與CH374U之間放了USB分析儀,在分析儀中數(shù)據(jù)都是有發(fā)送的。附上主要讀取數(shù)據(jù)的程序,這個(gè)是根據(jù)官方的CH374U_HID_UDISK這個(gè)程序包參考過(guò)來(lái)的,
/* 事物傳輸 */ /* SET IN OUT */ /* Timeout=0不重試 Timeout=0xffff無(wú)限重試 ,返回PID*/?
UINT8 Issue_Token( UINT8 PID, UINT8 Endp, UINT8 Tog, UINT16 Timeout )
{
UINT8 s, resp, err_resp, err_num = 0;
while(1)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 雖是死循環(huán),但終究有返回的 */
{
Write374Byte( REG_USB_H_PID, ( PID<<4 ) | Endp );
Write374Byte( REG_USB_H_CTRL, Tog? BIT_HOST_TRAN_TOG|BIT_HOST_RECV_TOG|BIT_HOST_START:BIT_HOST_START ); /* 啟動(dòng)傳輸 */
s = Wait374Interrupt( );
if( s == Failure )? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 設(shè)備超時(shí)無(wú)響應(yīng),最多重試三次*/
err_num++;?
else err_num = 0;
if( err_num == 3 )
return s;
Write374Byte( REG_INTER_FLAG, BIT_IF_TRANSFER | BIT_IF_USB_PAUSE ); /* 清中斷 ,必須清除傳輸暫停位*/
if( err_num == 0 )
{
s = Read374Byte( REG_USB_STATUS );
resp = s & BIT_STAT_DEV_RESP;
switch( PID )? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 分析令牌PID */
{
case DEF_USB_PID_SETUP:
case DEF_USB_PID_OUT:
if( resp == DEF_USB_PID_ACK )? ? ? ? ? ? ? ? ? ? /* 返回ACK */
return resp;
else if( resp == DEF_USB_PID_NAK )? ? ? ? ? ? ? ?/* 根據(jù)是否超時(shí)決定返回NAK */
{
if( Timeout == 0 )
return resp;?
else
{
if( Timeout < 0xffff) Timeout--;
}
}
else if( resp == DEF_USB_PID_STALL )? ? ? ? ? ? ?/* 返回STALL */
return resp;
else? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 出錯(cuò)或超時(shí)等 */
{
err_resp++;
if( err_resp == 3 )
return resp;
}
break;
case DEF_USB_PID_IN:
if( resp == DEF_USB_PID_DATA0 || resp == DEF_USB_PID_DATA1 ) /* 說(shuō)明收到了數(shù)據(jù)包,但不一定同步 */
{
if( s & BIT_STAT_TOG_MATCH )? ? ? ? ? ? ? ? ?/* 翻轉(zhuǎn)同步返回ACK */
return DEF_USB_PID_ACK;? ? ? ? ? ? ? ? ??
else? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 翻轉(zhuǎn)不同步返回當(dāng)前DATA值 */
return resp;
}
else if( resp == DEF_USB_PID_NAK )? ? ? ? ? ? ? ?/* 根據(jù)是否超時(shí)決定返回NAK */
{
if( Timeout == 0 )
return resp;
else
{
if( Timeout < 0xffff) Timeout--;
}
}
else if( resp == DEF_USB_PID_STALL )? ? ? ? ? ? ?/* 返回STALL */
return resp;
else? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 出錯(cuò)或超時(shí)等 */
{
err_resp++;
if( err_resp == 3 )
return resp;
}
break;
default:?
return Failure;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 非法PID */?
break;
}
}
}?
}
UINT8 Get_HidData( UINT8 Edp, UINT8 Tog, UINT8 *DataBuffer, UINT8 *len )
{
UINT8 s;
/* 設(shè)置待操作Hub口 */
//SelectHub( HubIndex );
/* 發(fā)送IN包 */
*len = 0;
s = Issue_Token( DEF_USB_PID_IN, Edp, Tog, 0 );? ? ? //不重試
if( s == DEF_USB_PID_ACK )
{
*len = Read374Byte( REG_USB_LENGTH );
Read374Block( RAM_HOST_RECV, *len, DataBuffer );
if(DataBuffer[1]!=0xfe){
printf( "lend 0x%x :0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n",*len,DataBuffer[0],DataBuffer[1], DataBuffer[2],DataBuffer[3],DataBuffer[4],DataBuffer[5]);
}
}
else
return s;
return Success;
}
/*==============================================寄存器測(cè)試程序====================================================================================*/
/*? ? ? ?函數(shù)說(shuō)明:主要用與測(cè)試寄存器,讀出積存器的值,寫(xiě)入并讀出寄存器的值,方便測(cè)試
? ? ? ? ?入口參數(shù):寄存器地址
? 出口參數(shù):無(wú)
/*=================================================================================================================================================*/
void? ReadPrintfReg( UINT8 addr)
{
? UINT8? value;
? value=Read374Byte(addr);
? printf("ADDRESS=%02X",(UINT16)addr);
? printf("? ?REGISTE=%02X\n",(UINT16)value);
}
/* 為printf和getkey輸入輸出初始化串口 */
voidmInitSTDIO( )
{
}
intmain( void )? // USB HUB
{
UINT8i, s, len;
UINT8 buf[64];
USART1_Config();//?????????
//P1&=0xF8; // ???U???????????????????
mDelaymS( 50 );? // 等待CH374復(fù)位完成
CH374_PORT_INIT( );? /* CH374接口初始化 */
mInitSTDIO( );? /* 為了讓計(jì)算機(jī)通過(guò)串口監(jiān)控演示過(guò)程 */
printf( "Start CH374 Host\n" );
Init374Host( );? // 初始化USB主機(jī)方式并啟用HUB功能
printf( "end CH374 Host\n" );
s = Read374Byte( 0x04 );
printf( "Read374Byte 0x%x\n" ,s);
//while(1);
while ( 1 )?
{
HostSetBusFree( );? // 設(shè)定USB主機(jī)空閑
printf( "Wait Device In\n" );
while ( 1 )?
{
if ( Query374Interrupt( ) ) HostDetectInterrupt( );? // 如果有USB主機(jī)中斷則處理
if ( ExcessNeedEnum( ) ) break;? ? ? ? ? ? ? ? ? ? ? ?// 有USB設(shè)備
}
mDelaymS( 250 );? // 由于USB設(shè)備剛插入尚未穩(wěn)定,故等待USB設(shè)備數(shù)百毫秒,消除插拔抖動(dòng)
if ( Query374Interrupt( ) ) HostDetectInterrupt( );? // 如果有USB主機(jī)中斷則處理
while( 1 )
? ? ? ?{
? ? ? ? ? ? ? ? ? ? ?
//HostSetBusReset( );//起用HUB功能時(shí)候,不需要此函數(shù)
ResetEndpBus( EndPointAddr );?
StartPort( EndPointAddr? );
ReadPrintfReg( 0x06 );
for ( i = 0; i < 100; i ++ )?
{? ? ? ? ? ? ?// 等待USB設(shè)備復(fù)位后重新連接
ReadPrintfReg( 0x02 );
if ( Query374Endport( ) ) break;? ?// 有USB設(shè)備
mDelaymS( 1 );
}
if ( Query374Interrupt( ) ) HostDetectInterrupt( );? // 如果有USB主機(jī)中斷則處理
if ( Query374Endport( ) )?
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 有USB設(shè)備
ChangeSpeed( EndPointAddr );? ?//檢查設(shè)備速度,不匹配切換
? if( Infor_DEV[1].Speed_Flag==1 )Write374Byte( REG_HUB_CTRL,Read374Byte(REG_HUB_CTRL)|BIT_HUB1_POLAR);
mDelaymS( 10 );
}
else?
{
printf( "Device gone !\n" );
if( ExcessNeedEnum ( )==FALSE )break;// 如果沒(méi)有需要枚舉的設(shè)備則退出
else continue;? // 設(shè)備已經(jīng)斷開(kāi),繼續(xù)等待
}
ReadPrintfReg( 0x03 );
mDelaymS( 50 );?
printf( "GetDeviceDescr: " );
s = GetDeviceDescr( buf );? // 獲取設(shè)備描述符
if ( s != USB_INT_SUCCESS )?
{
printf( "ERROR = %02X\n", (UINT16)s ); //for(s=0;s<20;s++) ReadPrintfReg(s);
Fail_Init( EndPointAddr );
if( !(ExcessNeedEnum( )) )break;? // 終止操作,等待USB設(shè)備拔出
else continue;
}
for ( i = 0; i < ( (PUSB_SETUP_REQ)SetupGetDevDescr ) -> wLengthL; i ++ ) printf( "%02X ", (UINT16)( buf[i] ) );
printf( "\n" );
printf( "SetUsbAddress: " );
printf("EndPointAddr=%02X\n",(UINT16)EndPointAddr );
s = SetUsbAddress( EndPointAddr );? ? ? ? ? ? ?// 設(shè)置USB設(shè)備地址
? ? ? ?
if ( s != USB_INT_SUCCESS )?
{
Fail_Init( EndPointAddr );
printf( "ERROR = %02X\n", (UINT16)s );
if( !(ExcessNeedEnum( ) ) )break;? // 終止操作,等待USB設(shè)備拔出
else continue;
}
printf( "\n" );
printf( "GetConfigDescr: " );
s = GetConfigDescr( buf );? // 獲取配置描述符
if ( s != USB_INT_SUCCESS )?
{
Fail_Init( EndPointAddr );
printf( "ERROR = %02X\n", (UINT16)s );
if( !(ExcessNeedEnum( )) )break;? ? ? ? ? ? ? ? ?// 終止操作,等待USB設(shè)備拔出
else continue;? //如果沒(méi)設(shè)備則等待拔出
}? //有未枚舉完的設(shè)備則繼續(xù)枚舉
i=( (PUSB_CFG_DESCR_LONG)buf )->itf_descr.bNumEndpoints;
Put_EndpInf_List( (PUSB_CFG_DESCR_LONG)buf, i );?
for ( i = 0; i < ( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL; i ++ ) printf( "%02X ", (UINT16)( buf[i] ) );
printf( "\n" );
/* 分析配置描述符,獲取端點(diǎn)數(shù)據(jù)/各端點(diǎn)地址/各端點(diǎn)大小等,更新變量endp_addr和endp_size等 */
printf( "SetUsbConfig: \n" );
s = SetUsbConfig( ( (PUSB_CFG_DESCR)buf ) -> bConfigurationValue );? // 設(shè)置USB設(shè)備配置
if ( s != USB_INT_SUCCESS )?
{
Fail_Init( EndPointAddr );
printf( "ERROR = %02X\n", (UINT16)s );
if( !(ExcessNeedEnum( )) )break;? // 終止操作,等待USB設(shè)備拔出
else continue;
}
else Infor_DEV[EndPointAddr].Already_Conf=1;
/* do something, read/write ...
len = out_endp_size;
Write374Block( RAM_HOST_TRAN, len, buf );
Write374Byte( REG_USB_LENGTH, len );
s = WaitHostTransact374( out_endp_addr, DEF_USB_PID_OUT, FALSE, 1000 );
s = WaitHostTransact374( in_endp_addr, DEF_USB_PID_IN, FALSE, 1000 );
len = Read374Byte( REG_USB_LENGTH );
Read374Block( RAM_HOST_RECV, len, buf );
len = out_endp_size;
Write374Block( RAM_HOST_TRAN, len, buf );
Write374Byte( REG_USB_LENGTH, len );
s = WaitHostTransact374( out_endp_addr, DEF_USB_PID_OUT, TRUE, 1000 );
s = WaitHostTransact374( in_endp_addr, DEF_USB_PID_IN, TRUE, 1000 );
len = Read374Byte( REG_USB_LENGTH );
Read374Block( RAM_HOST_RECV, len, buf );
*/
printf( "do something, read / write ......\n" );
if( Infor_DEV[EndPointAddr].Speed_Flag==1 )HostSetFullSpeed( );? ?// 如果是低速設(shè)備,則將總線速度切換到全速
printf("***********************\n");
printf( "SUCESS ENUMERATE\n" );? ?? ? ? ? ? //還需要枚舉的設(shè)備數(shù)量
printf("***********************\n");
s=ExcessNeedEnum( );? ? ? ? ? ? ? ? ? ? ? ? ?//在枚舉完畢最后一個(gè)設(shè)備時(shí)再次檢測(cè)有無(wú)設(shè)備
if( s==FALSE )
{printf("No device need Setconfig\n");
break; ? ? //沒(méi)有設(shè)備需要枚舉,則退出函數(shù)
}
}
WaitDeviceOut:? // ??USB????
printf( "Wait Device Out\n" );
while ( 1 ) {
if ( Query374Interrupt( ) ) HostDetectInterrupt( );? // ???USB???????
if ( Query374DeviceIn( ) == FALSE ) break;? // ??USB??
s = Get_HidData( 0x02, 1, buf, &len );? ?//獲取HID數(shù)據(jù)
#if 0
s = WaitHostTransact374( 0x02, DEF_USB_PID_IN, FALSE, 1000 );
//printf( "s ......0x%x\n", s );
len = Read374Byte( REG_USB_LENGTH );
if(len>0){
//printf( "len ......%d\n", len );
Read374Block( RAM_HOST_RECV, len, buf );
//for(i=0;i
//printf( "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n",buf[0],buf[1], buf[2],buf[3],buf[4],buf[5]);
//printf( "buf[%d]=0x%x\n", i, buf[i] );
//}
if(buf[1]!=0xfe)
printf( "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x \n",buf[0],buf[1], buf[2],buf[3],buf[4],buf[5]);
}
#endif
}
mDelaymS( 100 );? // ????????,??????
if ( Query374DeviceIn( ) ) goto WaitDeviceOut;? // ??????
//HostSetBusFree( );? // ??USB????,???????SOF
}
}
lend 0x20 :0x9 0x90 0x15 0x48 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x0 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x4c 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x0 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x59 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x0 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x54 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x0 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x6b 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x0 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x63 0x0 0x0? ?這個(gè)地方就沒(méi)有收到釋放的消息
lend 0x20 :0x9 0x90 0x15 0x68 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x0 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x6a 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x0 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x70 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x0 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x6a 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x0 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x6d 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x0 0x0 0x0
lend 0x20 :0x9 0x90 0x15 0x6d 0x0 0x0??這個(gè)地方就沒(méi)有收到釋放的消息
還有其他地方?jīng)]有收到按下和釋放的消息