首先,CH375B比CH375A兼容性是强了不少,在CH375A下枚举不成功的设备,CH375B几乎都枚举成功了。但在枚举一个SUN键盘时,出现一些问题,需要请教两个问题: 1 当设置完地址后,究竟需不需要再重新复位设备? 1)重新复位设备:除SUN键盘外,均能枚举成功,但所有设备在GET_INT_IN()中请求IN包时,CH375B不产生中断,所以操作设备时无数据送出。枚举SUN键盘时,在SET_IDLE()处CH375B不再产生中断。 2)不重新复位设备:除SUN键盘,手头所有设备均能正常工作,操作设备会产生相应的数据。枚举SUN键盘时,有的时候获取设备描述符会成功,大部分时候是在获取设备描述符时CH375B不产生中断,程序陷入死等状态。 2 当向设备发送完令牌后,CH375B为什么不产生中断,而令程序陷入死等状态?
1:设置地址后,不需要重新复位设备 2:把键盘插在计算机上,对比计算机的操作流程,看看你的程序中是否有缺少的步骤
不会有缺少的步骤,要是有,也不会有大多数设备能正常工作的情况了。 其实我现在只有一个问题了,就是那个SUN键盘的枚举,其他的,可以说已经成功了。 而这个SUN键盘,设置地址前的操作均是成功的,设置地址后,就很难说了,有的时候能往下进行一步,有的时候一步也进行不下去。 下面是设置地址后不复位的情况: get_device_descr 12 01 10 01 00 00 00 08 30 04 05 00 00 02 00 00 00 01 set_addr get_device_descr again
再下面的情况是设置地址后再复位的枚举情况: get_device_descr 12 01 10 01 00 00 00 08 30 04 05 00 00 02 00 00 00 01 set_addr get_device_descr again 12 01 10 01 00 00 00 08 30 04 05 00 00 02 00 00 00 01 get_config_desc 09 02 22 00 01 01 00 a0 32 config 2 09 02 22 00 01 01 00 a0 32 09 04 00 00 01 03 01 01 00 09 21 00 01 21 01 22 40 00 07 05 81 03 08 00 0a set_config set idle
追踪程序,这两种现象最后都归结为status=wait_interrupt(),说明ch375没有产生中断。
设置完地址后,通常至少等待3mS才能继续操作,看看计算机等了多长时间才去操作的
设置地址后我等待了100ms.
建议你用BUSHOUND软件去抓取数据看有没有特殊的操作步骤,不能因为大多数的没有问题就说没问题,我们确实碰到过. 另外你在切换速度后等待50MS后获取设备描述符看看是否可以. 按照标准流程来说设置完地址后是不需要复位的.
如1楼所说你可以将SUN键盘连接到电脑上,用BUSHOUND软件来抓取PC和其通讯的数据,看看对于该键盘是否有特殊的操作
我把延时程序放在了下面那个位置,运行结果还是和以前一样, void main() { unsigned char i; mInitSTDIO( ); delayms(250); set_usb_mode( 6 ); /* 设置USB主机模式, 如果设备端是CH37X, 那么5和6均可 */ #ifdef TEST_LOW_SPEED set_freq(0x01); //使375B进入低速模式 #endif while(1) { while ( wait_interrupt()!=USB_INT_CONNECT ); /* 等待设备端连接上来 */ delayms(150); reset_device(); delayms(5); set_freq(0x01); //使375B进入低速模式 delayms(50); //建议添加的延时程序
printf("get_device_descr\n"); // get_descr(0x01);//获取设备描述符
Request.Req.bmRequestType=0x80; 运行结果如下: get_device_descr 12 01 10 01 00 00 00 08 30 04 05 00 00 02 00 00 00 01 set_addr get_device_descr again //程序陷入死等中断出现的状态
我这儿bushound看不到设置地址的操作(所有USB设备的枚举过程都看不到),除此之外,SUN键盘与其他设备相比,枚举过程没有不一样的地方。
把您的程序贴出来看看.
void main() { unsigned char i; mInitSTDIO( ); delayms(250); set_usb_mode( 6 ); /* 设置USB主机模式, 如果设备端是CH37X, 那么5和6均可 */ #ifdef TEST_LOW_SPEED set_freq(0x01); //使375B进入低速模式 #endif while(1) { while ( wait_interrupt()!=USB_INT_CONNECT ); /* 等待设备端连接上来 */ delayms(150); reset_device(); delayms(5); set_freq(0x01); //使375B进入低速模式 delayms(50);
printf("get_device_descr\n"); // get_descr(0x01);//获取设备描述符
Request.Req.bmRequestType=0x80; Request.Req.bRequest=0x06; Request.Req.wValue=0x0001; Request.Req.wIndex=0x0000; Request.Req.wLength=0x1200; if(get_descr_ex()==1) { for(i=0;i!=data_buf[0];i++) printf("%02x ",(unsigned int)data_buf[i]); printf("\n"); } else printf("get device descr failed\n");
printf("set_addr\n"); set_addr(5);//设置地址 delayms(200);
// reset_device(); // set_freq(01); // delayms(50);
printf("get_device_descr again\n"); Request.Req.bmRequestType=0x80; Request.Req.bRequest=0x06; Request.Req.wValue=0x0001; Request.Req.wIndex=0x0000; Request.Req.wLength=0x1200; if(get_descr_ex()==1) { for(i=0;i!=data_buf[0];i++) printf("%02x ",(unsigned int)data_buf[i]); printf("\n"); } else printf("get device descr failed\n");
printf("get_config_desc\n"); // get_descr(0x02);//获取配置描述符
Request.Req.bmRequestType=0x80; Request.Req.bRequest=0x06; Request.Req.wValue=0x0002; Request.Req.wIndex=0x0000; Request.Req.wLength=0x0900; if(get_descr_ex()==1) { for(i=0;i!=data_buf[0];i++) printf("%02x ",(unsigned int)data_buf[i]); printf("\n"); if(data_buf[4]!=0x01)flag_interface_2=1;//有多个接口 } else printf("get config descr failed\n"); printf("config 2\n"); if(data_buf[2]>0x09) { flag_config_2=1; Request.Req.bmRequestType=0x80; Request.Req.bRequest=0x06; Request.Req.wValue=0x0002; Request.Req.wIndex=0x0000; Request.Req.wLength=0x0000|((unsigned int)data_buf[2]<<8); if(get_descr_ex()==1) { for(i=0;i!=data_buf[2];i++) printf("%02x ",(unsigned int)data_buf[i]); printf("\n"); flag_config_2=0; } else printf("get device descr again failed\n"); }
parse_config_descr();//保存描述符中一些值 printf("set_config\n"); set_config(config_value);//设置配置 // if(set_config_ex()!=1)printf("set config failed\n"); printf("set idle\n"); if(set_idle()!=1)printf("set idle failed\n"); printf("get_report\n"); Request.Req.bmRequestType=0x81; Request.Req.bRequest=0x06; Request.Req.wValue=0x0022; Request.Req.wIndex=0x0000; Request.Req.wLength=0x0000|((unsigned int)(report_descr_len+0x40)<<8); if(get_report_descr_ex()==1) { for(i=0;i!=report_cou;i++) printf("%02x ",(unsigned int)data_buf[i]); printf("\n"); } else printf("get report descr failed\n"); // printf("set report\n"); //对于键盘这一步,是点亮指示灯 // if(set_report()!=1)printf("set report failed\n"); printf("OK!\n"); do { get_int_in(); //发送从中断端点读数据的令牌 if(flag_output) { for(i=0;i!=data_len;i++) printf("%02x ",(unsigned short)data_buf[i]); printf("\n"); flag_output=0; } else delayms(10); }while(1); while ( wait_interrupt()!=USB_INT_DISCONNECT ); /* 等待设备端连接上来 */ } }
这个程序是从你们网站上下载的
我所做的改动: 1把子程序void intt0()隐掉 2void set_freq(void)改用ch375a的操作方式 3串口初使化设置为12M,9600bps 4更改void get_int_in()函数的定义 5主程序更改比较大,再有硬件控制信号的更改。
发现一个问题,请教一下你们如何解释: 枚举SUN键盘时,设置地址后不复位,单片机会一直等ch375产生中断,导致程序不能往下运行,此时,我若按一下键盘上的任一按键,得到设备描述符的命令就会成功,然后程序会在“得到配置描述符”时死等ch375中断,我若再按一下按键,程序又会往下运行,循环如此,程序会运行到最后,键盘枚举成功!请问,该如何解释这种现象?