CH374U與轉(zhuǎn)換MIDI丟包問(wèn)題

請(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)]有收到按下和釋放的消息


您好,這邊傳輸采用中斷傳輸?shù)脑捫枰獓?yán)格按照端點(diǎn)輪詢時(shí)間獲取數(shù)據(jù),這份代碼采用的是while循環(huán)向設(shè)備發(fā)送IN包要數(shù)據(jù),在要數(shù)據(jù)時(shí)加了打印會(huì)使IN包的間隔時(shí)間變長(zhǎng)。端點(diǎn)描述符的最后一個(gè)字節(jié)規(guī)定了主機(jī)發(fā)送IN包的時(shí)間間隔,比較好的做法是,用定時(shí)器間隔發(fā)送IN包問(wèn)設(shè)備要數(shù)據(jù)。


只有登錄才能回復(fù),可以選擇微信賬號(hào)登錄

国产91精品新入口,国产成人综合网在线播放,九热这里只有精品,本道在线观看,美女视频a美女视频,韩国美女激情视频,日本美女pvp视频