用STM32+CH374S驱动USB键盘,出现一个非常奇怪的问题。刚烧写完程序(不断电)进去的可以正常读取键盘数据,也非常稳定。但如果断一次电再去读取键盘时发现就无法获取到数据了。
对比一下启动后调试信息,烧写后未断电重启,endp_in_addr = 01;如果断电后再重启发现endp_in_addr = 04。不知道这是什么情况,请版主指教,非常感谢!
int UsbKey(void)
{
UINT8 i, s,close_bit_flag=0;
//由于报告描述符大小不定,缓冲区的大小最好定义大些
UINT8 buf[80];
// 等待CH374复位完成
mDelaymS( 50 );
// CH374接口初始化
CH374_PORT_INIT( );
// 初始化USB主机
Init374Host( );
//设置主机空闲
HostSetBusFree( );
// 由于USB设备刚插入尚未稳定,故等待USB设备数百毫秒,消除插拔抖动
if(ch374_flag == 1)
{
ch374_flag = 0;
//while(1)
//{
// if ( Query374Interrupt( ) ) HostDetectInterrupt( );
// if ( Query374DeviceIn( ) ) break;
//}
mDelaymS( 10 );
if ( Query374Interrupt( ) ) HostDetectInterrupt( ); // 如果有USB主机中断则处理
LCDprintf( "Reset Device\n" );
HostSetBusReset( ); // USB总线复位
for ( i = 0; i < 100; i ++ ) // 等待USB设备复位后重新连接
{
if ( Query374DeviceIn( ) ) break; // 有USB设备
mDelaymS( 1 );
}
if ( Query374Interrupt( ) ) HostDetectInterrupt( ); // 如果有USB主机中断则处理
if ( Query374DeviceIn( ) ) // 有USB设备
{
if ( Query374DevFullSpeed( ) )
{
LCDprintf( "Start Full-Speed Device\n" );
HostSetFullSpeed( ); // 检测到全速USB设备
LOW_SPEED_BIT=0;
}
else
{
LCDprintf( "Start Low-Speed Device\n" );
HostSetLowSpeed( ); // 检测到低速USB设备
LOW_SPEED_BIT=1;
}
}
else
{
return -1; // 设备已经断开,继续等待
}
mDelaymS( 50 );
close_bit_flag=0;
LCDprintf( "GetDeviceDescr: " );
s = GetDeviceDescr( buf ); // 获取设备描述符
LCDprintf("device_status=%x \n",(unsigned short)s);
if ( s != USB_INT_SUCCESS )
{
goto WaitDeviceOut; // 终止操作,等待USB设备拔出
}
for ( i = 0; i < ( (PUSB_SETUP_REQ)SetupGetDevDescr ) -> wLengthL; i ++ ) LCDprintf( "%x ", (UINT16)( buf[i] ) );
LCDprintf( "\n" );
s = SetUsbAddress( 0x02 ); // 设置USB设备地址
LCDprintf("address_status=%x\n",(unsigned short)s);
if ( s != USB_INT_SUCCESS )
{
goto WaitDeviceOut; // 终止操作,等待USB设备拔出
}
s = GetConfigDescr( buf ); // 获取配置描述符
LCDprintf("config_status=%x\n",(unsigned short)s);
if ( s != USB_INT_SUCCESS )
{
goto WaitDeviceOut; // ????,??USB????
}
// 分析配置描述符,获取端点数据/各端点地址/各端点大小等,更新变量endp_addr和endp_size等
s = SetUsbConfig( ( (PUSB_CFG_DESCR)buf ) -> bConfigurationValue ); // 设置USB设备配置
if ( s != USB_INT_SUCCESS )
{
// LCDprintf( "ERROR = %x\n", (UINT16)s );
goto WaitDeviceOut; // 终止操作,等待USB设备拔出
}
else LCDprintf( "SetUsbConfig_success\n" );
//-------------------------以下进行HID类的简单操作-----------------------------------------------------------
LCDprintf("Set_Idle\n");
s=Set_Idle( ); //设置IDLE,这个步骤是按照HID类的协议来做的
if(s!=USB_INT_SUCCESS)
{
LCDprintf("Set_Idle_Err=%x\n",(unsigned short)s);
if(s&0x0f==USB_INT_RET_STALL) goto next_operate1; //返回STALL可能本身不支持
}
else LCDprintf("Set_idle success\n");
next_operate1:
LCDprintf("Get_Hid_Des\n");
s=Get_Hid_Des(buf); // 获取报表描述符描述符
if(s==USB_INT_SUCCESS)
{
LCDprintf("HID_Desc: ");
for(i=0;i!=hid_des_leng;i++) LCDprintf("%x ",(unsigned short)buf[i]);
LCDprintf("\n");
}
else
{
goto WaitDeviceOut; //出错退出
}
LCDprintf("Set_Report \n");
//对于键盘发Set_Report来点亮灯,对于鼠标则不需要这一步
buf[0]=0x01;
s=Set_Report(buf); //设置报表
if(s==USB_INT_SUCCESS)
{
LCDprintf("Set_Report success\n");
}
else
{
LCDprintf("Set_Report Err=%x\n",(unsigned short)s); //设置报告出错
if(s&0x0f==USB_INT_RET_STALL)
goto next_operate2; //返回STALL可能本身不支持
}
next_operate2:
// 下面开始读取数据
//实际在读取数据的时候,
//要先发送中断端点的令牌来读取数据,
//接着才能获取到数据
//LCD_Clear(0x001F);
tog1=FALSE; //开始取DATA0
while(1)
{
s=Interrupt_Data_Trans(buf);
// printf("s:%x \n",(unsigned short)s);
if(s==USB_INT_SUCCESS)
{
for(i=0;i!=8;i++) LCDprintf("%02x ",(unsigned short)buf[i]);
LCDprintf("\n");
}
else if(s==USB_INT_DISCONNECT) // 这个是为了知道设备拔出产生的中断状态
{
close_bit_flag=1;
break;
}
}
return 0;
WaitDeviceOut: // 这个是为了知道设备拔出产生的中断状态
LCDprintf( "Wait Device Out\n" );
usbrst_flag = 1;
if(close_bit_flag==0){
while ( 1 )
{
if ( Query374Interrupt( ) ) HostDetectInterrupt( ); // 如果有USB主机中断则处理
if ( Query374DeviceIn( ) == FALSE ) break; // 没有USB设备
}
}
mDelaymS( 100 ); // 等待设备完全断开,消除插拔抖动
return -2;
}
else
return -3;
}