请教一下,目前用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 这个地方就没有收到释放的消息
还有其他地方没有收到按下和释放的消息