完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我的芯片用的是CH549L,注册成HID设备下的第0x0C项consumer类型应用。目的是通过旋钮调节电脑音量。
正常使用都没有问题。但是有一个BUG是,部分时候电脑关机以后重启,这时候设备就不能工作了,必须要重新插拔一下HID设备才行。 通过大量测试后初步判断,是因为电脑重启时,整个过程中电脑的USB口没有断电,以至于重新开机以后,HID设备并没有重启。电脑这边枚举的USB设备的数据已经清空了,但是我这个HID设备却还记着之前枚举的信息,这时候电脑没有检测到重新插入的USB设备的信号,就不会自动的重新枚举。导致旧的信息不能用了,以至于失效。 我尝试了一个简单的办法,就是人工判断设备失效以后,按一下一下我的板上的一个按钮,然后在程序里直接goto到程序的最开始,直接重新初始化,但是不能够解决这个问题。 所以我想问问,有没有什么能够检测到USB通信失效了的变量啊之类的?还有检测到失效以后,又如何通过软件重新让电脑枚举我的设备? ---------------------------- 我的代码主要修改自给的demo代码里面的“CompositeKM.C”文件。上面附上我的描述符,USB中断服务函数没敢改。 /*设备描述符*/ UINT8C DevDesc[] = { 0x12, // bLength。描述符长度(18字节,十六进制为0x12),就是标志描述符数据结构的长度。 0x01, // bDescriptorType。描述符类型。0x01为设备描述符 0x00,0x02, // bcdUSB。设备使用的USB协议版本。表示形式0xJJMN版本JJ.M.N(JJ-主要版本号,M-次要版本号,N-次要版本)。 // 例子:如果是USB2.0,写成:0200H。如果是USB1.1,写成。0110H 如果是USB3.11,写成:0311H。 // 注意是小端模式,所以低字节写在前面 0x00, // bDeviceClass。类代码。表示设备类型。为0时指示用接口描述符来标识类别。详见https://www.usb.org/defined-class-codes 0x00, // bDeviceSubClass。子类型。 0x00, // bDeviceProtocol。设备使用的协议。 THIS_ENDP0_SIZE, // bMaxPackeSize0。端点一次最大传多少个字节。 0x86,0x1a, // idVender。厂商ID。 0xe1,0xe6, // idProduct。产品ID。 0x00,0x01, // bcdDevice。产品版本号。 0x01, // iManufacturer。描述厂商的字符串的索引。 0x02, // iProduct。描述产品的字符串的索引。 0x00, // iSerialNumber。描述产品序列号字符串的索引. 0x01 // bNumConfigurations。指示设备有多少个配置 }; /*字符串描述符*/ // 语言ID描述符 UINT8C MyLangDescr[] = { 0x04, // bLength。描述符长度。 0x03, // bDescriptorType。描述符类型。语言ID描述符也是字符串描述符,类型为0x03。 0x09, 0x04 // wLANGID[0]。要支持的语言ID号。 // wLANGID[n]。有可能会支持多种语言。但是这里没写了。 }; // 厂家信息描述符 UINT8C MyManuInfo[] = { 0x0E, // bLength。描述符长度。 0x03, // bDescriptorType。描述符类型。字符串描述符类型为0x03。 'C', 0, 'S', 0, 'Y', 0, '.', 0, 'U', 0, 'S', 0, 'B', 0 // bString。UNICODE编码的字符串。 }; // 产品信息描述符 UINT8C MyProdInfo[] = { 0x0C, // bLength。描述符长度。 0x03, // bDescriptorType。描述符类型。字符串描述符类型为0x03。 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0 // bString。UNICODE编码的字符串。 }; /*HID类报表描述符*/ UINT8C ConsumerRepDesc[] = { 0x05,0x0C, // Usage Page (Consumer) 0x09,0x01, // Usage(Consumer Control) 0xA1,0x01, // Collection (Application), Main Items —— Collection —— Application 0x15,0x00, // Logical Minimum (0), Global Items —— Logical Minimum —— 0 0x25,0x01, // Logical Maximum (1), Global Items —— Logical Maximum —— 1 0x75,0x01, // Report Size (1), Global Items —— Report Size —— 1 0x95,0x01, // Report Count (1), Global Items —— Report Count —— 1 0x09,0xCD, // Usage(Play/Pause),开始暂停 0x81,0x06, // Input (Data, Value, Relative), 0x09,0xB5, // Usage(Scan Next Track),下一曲 0x81,0x06, // Input (Data, Value, Relative), 0x09,0xB6, // Usage(Scan Previous Track),上一曲 0x81,0x06, // Input (Data, Value, Relative), 0x09,0xE2, // Usage(Mute),静音 0x81,0x06, // Input (Data, Value, Relative), 0x09,0xE9, // Usage(Volume Increment),音量+ 0x81,0x06, // Input (Data, Value, Relative), 0x09,0xEA, // Usage(Volume Decrement),音量- 0x81,0x06, // Input (Data, Value, Relative), 0x09,0xB3, // Usage(Fast Forward),快进 0x81,0x02, // Input (Data, Value, Absolute), 0x09,0xB4, // Usage(Rewind),倒带 0x81,0x02, // Input (Data, Value, Absolute), 0xC0 // End Collection, Main Items —— End Collection }; /*配置描述符集合(必须按照顺序)*/ UINT8C CfgDesc[] = { // 标准配置描述符 0x09, // bLength。配置本描述符的长度。 0x02, // bDescriptorType。描述符类型。配置描述符为0x02。 0x3b,0x00, // wTotalLength。配置描述符集合总长度。 0x01, // bNumInterfaces。当前配置下面有多少个接口。 0x01, // bConfigurationValue。当前配置的标识。一个USB设备可能有多个配置,但是当前只能选择一种配置。 0x00, // iConfiguration。描述该配置的字符串的索引值。如果没有字符串,那这个值就是0。 0xE0, // bmAttributes。在这个配置下,设备的一些特性。 // D7是保留位,默认为1; // D6表示供电方式,0是自供电,1是总线供电; // D5表示是否支持远程唤醒,为1表示设备支持远程唤醒; // D4~D0保留,默认为0。 0x32, // bMaxPower。配置设备需要的电流。单位是2ma。如果一个设备耗电量100ma,那么本字节设置为0x32即可。 // 接口描述符(Consumer) 0x09, // bLength。配置本描述符的长度。 0x04, // bDescriptorType。描述符类型。接口描述符为0x04。 0x00, // bInterfaceNumber。接口编号。如果一个配置有多个接口的话,那么每个接口的编号都有一个独立的编号,编号从0开始递增。 0x00, // bAlternateSetting。备用接口编号。一般很少用,设置为0。 0x01, // bNumEndpoints。该接口使用的端点个数。 0x03, // bInterfaceClass。接口类。当设备描述符设备类型bDeviceClass为0时,也就是指示用接口描述符来标识类别。 0x01, // bInterfaceSubClass。接口子类。 0x01, // bInterfaceProtocol。接口协议。 0x00, // iInterface。此接口的字符串索引值。没有的话一般为0. // HID类描述符 0x09, // bLength。配置本描述符的长度。 0x21, // bDescriptorType。描述符类型。HID描述符为0x21。 0x11,0x01, // bcdHID。HID设备所遵循的HID版本号,为4位16进制的BCD码。1.0即0x0100,1.1即0x0101,2.0即0x0200。 0x00, // bCountryCode。HID设备国家/地区代码。 0x01, // bNumDescriptor。HID设备支持的下级描述符的数量。由于HID设备至少需要包括一个报告描述符,故其值至小为0x01,一般的HID设备也为1,也就是有一个报告描述符,物理描述符很少用到。 0x22, // bDescriptorTyep。下级描述符的类型。下级描述符第1个必须是报告描述符,所以这里存放报告描述符类型,报告描述符的类型为0x22。 sizeof(ConsumerRepDesc)&0xFF,sizeof(ConsumerRepDesc)>>8, // wDescriptorLength。下级描述符的长度 // 端点描述符(Consumer) 0x07, // bLength。配置本描述符的长度。 0x05, // bDescriptorType。描述符类型。端点描述符为0x05。 0x81, // bEndpointAddress。 // Bit 3…0: 端点编号; // Bit 6…4: 保留,默认为0; // Bit 7:如果是控制端点可以忽略,因为控制端点有两个方向,否则一般表示数据传输方向,0 = OUT endpoint 1 = IN endpoint。 0x03, // bmAttributes。Bits 1..0: 表示传输类型 // 00 = Control-控制传输 // 01 = Isochronous-同步传输 // 10 = Bulk-批量传输 // 11 = Interrupt-中断传输 // Bits 7..2: 还没讲 ENDP1_IN_SIZE,0x00, // wMaxPackeSize(双字节)。表示当前配置下此端点能够接收或发送的最大数据包的大小。 0x0a // bInterval。查询时间。就是主机多久和设备通讯一次。低速和全速称为帧,一个值代表1ms。高速称为微帧,一个值代表125us。 }; |
|
相关推荐
1个回答
|
|
有几个还需要确认的点:1、可以在USB中断函数中处理控制传输(回传描述符)的地方加个printf,看一下在开机时电脑是否有做枚举,通常电脑重启之后会重新枚举的。
2、在相同电脑环境下,其余的键盘鼠标能不能正常工作,是否有条件对USB数据线进行抓包,看一下关机到开机这个过程中您的代码行为和键鼠行为的差异。 3、你说的当出现这种问题的时候goto到开头重新运行,需要先将USB_CTRL清零,延时一会,在做USB的初始化,目的是撤销数据线上的上拉电阻,然后重新生效。此时是否能够正常工作起来。 4、解决这个问题,可以尝试使用SOF中断,通常电脑关机后总线会处于挂起,USB中断中会进入suspend,以这个时间节点等后续是否有SOF中断,如果超过若干SOF周期还是没有产生SOF中断,可以判断电脑处于关掉或者不和你通讯的状态,这个时候可以尝试执行3中的操作。具体逻辑可以测试后修改。 |
|
|
|
只有小组成员才能发言,加入小组>>
491 浏览 1 评论
CH579M+RT-Thread,RTC从Sleep模式唤醒失败是什么原因?
2884 浏览 2 评论
2374 浏览 1 评论
835浏览 2评论
511浏览 1评论
CH32F103C8T6使用当前官网上的CDC例程会出现设备描述符请求失败
379浏览 1评论
657浏览 1评论
riscv-none-embed-objcopy: \'PWM_Output.elf\': No such file这个咋解决,
396浏览 1评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-2 13:02 , Processed in 0.846495 second(s), Total 46, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号