CH374U与转换MIDI丢包问题

请教一下,目前用CH374U链接USBmidi后发现有丢包现象,具体情况就是钢琴琴键按下或者放手的时候,有时候获取不到这包数据,我在midi钢琴与CH374U之间放了USB分析仪,在分析仪中数据都是有发送的。附上主要读取数据的程序,这个是根据官方的CH374U_HID_UDISK这个程序包参考过来的,

/* 事物传输 */ /* SET IN OUT */ /* Timeout=0不重试 Timeout=0xffff无限重试 ,返回PID*/ 

UINT8 Issue_Token( UINT8 PID, UINT8 Endp, UINT8 Tog, UINT16 Timeout )

{

UINT8 s, resp, err_resp, err_num = 0;

while(1)                                                        /* 虽是死循环,但终究有返回的 */

{

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 ); /* 启动传输 */

s = Wait374Interrupt( );

if( s == Failure )                                         /* 设备超时无响应,最多重试三次*/

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 )               /* 根据是否超时决定返回NAK */

{

if( Timeout == 0 )

return resp; 

else

{

if( Timeout < 0xffff) Timeout--;

}

}

else if( resp == DEF_USB_PID_STALL )             /* 返回STALL */

return resp;

else                                             /* 出错或超时等 */

{

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 ) /* 说明收到了数据包,但不一定同步 */

{

if( s & BIT_STAT_TOG_MATCH )                 /* 翻转同步返回ACK */

return DEF_USB_PID_ACK;                  

else                                         /* 翻转不同步返回当前DATA值 */

return resp;

}

else if( resp == DEF_USB_PID_NAK )               /* 根据是否超时决定返回NAK */

{

if( Timeout == 0 )

return resp;

else

{

if( Timeout < 0xffff) Timeout--;

}

}

else if( resp == DEF_USB_PID_STALL )             /* 返回STALL */

return resp;

else                                             /* 出错或超时等 */

{

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;

/* 设置待操作Hub口 */

//SelectHub( HubIndex );

/* 发送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;

}



/*==============================================寄存器测试程序====================================================================================*/

/*       函数说明:主要用与测试寄存器,读出积存器的值,写入并读出寄存器的值,方便测试

         入口参数:寄存器地址

  出口参数:无

/*=================================================================================================================================================*/

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复位完成

CH374_PORT_INIT( );  /* CH374接口初始化 */

mInitSTDIO( );  /* 为了让计算机通过串口监控演示过程 */

printf( "Start CH374 Host\n" );

Init374Host( );  // 初始化USB主机方式并启用HUB功能


printf( "end CH374 Host\n" );

s = Read374Byte( 0x04 );

printf( "Read374Byte 0x%x\n" ,s);

//while(1);

while ( 1 ) 

{

HostSetBusFree( );  // 设定USB主机空闲

printf( "Wait Device In\n" );

while ( 1 ) 

{

if ( Query374Interrupt( ) ) HostDetectInterrupt( );  // 如果有USB主机中断则处理

if ( ExcessNeedEnum( ) ) break;                       // 有USB设备

}

mDelaymS( 250 );  // 由于USB设备刚插入尚未稳定,故等待USB设备数百毫秒,消除插拔抖动

if ( Query374Interrupt( ) ) HostDetectInterrupt( );  // 如果有USB主机中断则处理

while( 1 )

       {

                     

//HostSetBusReset( );//起用HUB功能时候,不需要此函数

ResetEndpBus( EndPointAddr ); 

StartPort( EndPointAddr  );

ReadPrintfReg( 0x06 );

for ( i = 0; i < 100; i ++ ) 

{             // 等待USB设备复位后重新连接

ReadPrintfReg( 0x02 );

if ( Query374Endport( ) ) break;   // 有USB设备

mDelaymS( 1 );

}

if ( Query374Interrupt( ) ) HostDetectInterrupt( );  // 如果有USB主机中断则处理

if ( Query374Endport( ) ) 

{                                                    // 有USB设备

ChangeSpeed( EndPointAddr );   //检查设备速度,不匹配切换

  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;// 如果没有需要枚举的设备则退出

else continue;  // 设备已经断开,继续等待

}

ReadPrintfReg( 0x03 );

mDelaymS( 50 ); 

printf( "GetDeviceDescr: " );

s = GetDeviceDescr( buf );  // 获取设备描述符

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设备拔出

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 );             // 设置USB设备地址

       

if ( s != USB_INT_SUCCESS ) 

{

Fail_Init( EndPointAddr );

printf( "ERROR = %02X\n", (UINT16)s );

if( !(ExcessNeedEnum( ) ) )break;  // 终止操作,等待USB设备拔出

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设备拔出

else continue;  //如果没设备则等待拔出

}  //有未枚举完的设备则继续枚举

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" );

/* 分析配置描述符,获取端点数据/各端点地址/各端点大小等,更新变量endp_addr和endp_size等 */


printf( "SetUsbConfig: \n" );

s = SetUsbConfig( ( (PUSB_CFG_DESCR)buf ) -> bConfigurationValue );  // 设置USB设备配置

if ( s != USB_INT_SUCCESS ) 

{

Fail_Init( EndPointAddr );

printf( "ERROR = %02X\n", (UINT16)s );

if( !(ExcessNeedEnum( )) )break;  // 终止操作,等待USB设备拔出

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( );   // 如果是低速设备,则将总线速度切换到全速

printf("***********************\n");

printf( "SUCESS ENUMERATE\n" );             //还需要枚举的设备数量

printf("***********************\n");

s=ExcessNeedEnum( );                         //在枚举完毕最后一个设备时再次检测有无设备

if( s==FALSE )

{printf("No device need Setconfig\n");

break;     //没有设备需要枚举,则退出函数

}

}


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数据

#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   这个地方就没有收到释放的消息

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  这个地方就没有收到释放的消息

还有其他地方没有收到按下和释放的消息


您好,这边传输采用中断传输的话需要严格按照端点轮询时间获取数据,这份代码采用的是while循环向设备发送IN包要数据,在要数据时加了打印会使IN包的间隔时间变长。端点描述符的最后一个字节规定了主机发送IN包的时间间隔,比较好的做法是,用定时器间隔发送IN包问设备要数据。


只有登录才能回复,可以选择微信账号登录