上两节我们实现了USB鼠标和USB键盘的实例,也许有人会问能不能用一套硬件同时实现USB鼠标和USB键盘的功能,答案是肯定的,而且这种应用场合是有的,比如带鼠标功能的多媒体键盘。
实现这种USB HID复合设备有两种方法,在《USB HID协议入门》一节已经讲到其中一种方法,说一个USB HID设备可以包含多种功能的报告描述符合集,这样可以实现复合设备,如带鼠标功能的USB键盘,这种复合键盘可以通过在报告描述里包含键盘和鼠标两种报告来实现,两个报告用报告ID来区分。这节我们就用这种方法来实现同时带鼠标和键盘功能的USB HID复合设备,有关另外一种方法的详细教程和实例可以参考本工作室推出的USB学习板。
既然可以用“在报告描述里包含键盘和鼠标两种报告来实现”,那么我们就把上两节的键盘和鼠标实例的报告描述符放在一起,再加上报告ID就是了,修改后的报告描述符如下:
- code char MouseReportDescriptor[119] = {
-
-
-
- 0x05, 0x01,
-
-
- 0x09, 0x06,
-
-
- 0xa1, 0x01,
-
-
- 0x85, 0x01,
-
-
- 0x05, 0x07,
-
-
- 0x19, 0xe0,
-
- 0x29, 0xe7,
-
- 0x15, 0x00,
-
- 0x25, 0x01,
-
- 0x75, 0x01,
-
- 0x95, 0x08,
-
-
- 0x81, 0x02,
-
-
-
-
-
-
-
-
- 0x95, 0x01,
-
- 0x75, 0x08,
-
- 0x81, 0x03,
-
-
-
-
- 0x95, 0x05,
-
- 0x75, 0x01,
-
- 0x05, 0x08,
-
- 0x19, 0x01,
-
- 0x29, 0x05,
-
-
- 0x91, 0x02,
-
-
- 0x95, 0x01,
-
- 0x75, 0x03,
-
- 0x91, 0x03,
-
-
-
-
-
- 0x95, 0x06,
-
- 0x75, 0x08,
-
- 0x15, 0x00,
-
- 0x25, 0xFF,
-
- 0x05, 0x07,
-
- 0x19, 0x00,
-
- 0x29, 0x65,
-
- 0x81, 0x00,
-
-
-
-
-
-
-
- 0xc0 ,
-
-
- 0x05, 0x01,
- 0x09, 0x02,
- 0xa1, 0x01,
- 0x85, 0x02,
- 0x09, 0x01,
- 0xa1, 0x00,
- 0x05, 0x09,
- 0x19, 0x01,
- 0x29, 0x03,
- 0x15, 0x00,
- 0x25, 0x01,
- 0x95, 0x03,
- 0x75, 0x01,
- 0x81, 0x02,
- 0x95, 0x01,
- 0x75, 0x05,
- 0x81, 0x03,
- 0x05, 0x01,
- 0x09, 0x30,
- 0x09, 0x31,
- 0x09, 0x38,
- 0x15, 0x81,
- 0x25, 0x7f,
- 0x75, 0x08,
- 0x95, 0x03,
- 0x81, 0x06,
- 0xc0,
- 0xc0
- };
这个报告描述符定义了两个报告输入报告(即数据包)和一个输出报告,两个输入报告中,一个是键盘,一个是鼠标,输出报告是用于指示LED状态的,两个输出报告所定义的数据包格式可以参考上两节内容。
由于电路板上只有两个按键,所有用K1模拟鼠标左移,K2 模拟键盘上的Windows图标键(按下K2后会弹出开始菜单),其代码如下:
- void main()
- {
- unsigned char i = 0;
- signed char cKeyIn[9];
- static bit bKey1Pressed = 0;
- static bit bKey2Pressed = 0;
-
- if (Init_D12()!=0)
- return;
-
- IT0 = 0;
-
- EX0 = 1;
- PX0 = 0;
- EA = 1;
-
- P0 = 0;
-
- while(1)
- {
- usbserve();
- if(bEPPflags.bits.configuration)
- {
-
- if(bEPPflags.bits.ep2_rxdone )
- {
- bEPPflags.bits.ep2_rxdone = 0;
-
-
- if(EpBuf[1] & 0x01)
- {
- P0 = 0x01;
- }
- else
- {
- P0 = 0x00;
- }
-
- }
-
- K1 = 1;
- K2 = 1;
-
- for(i=0;i<100;i++);
-
- if(~K1 )
- {
- cKeyIn[0]=2;
-
- cKeyIn[1]=0;
- cKeyIn[2]=-1;
- cKeyIn[3]=0;
- cKeyIn[4]=0;
-
- D12_WriteEndpoint(5,5,cKeyIn);
- }
-
- if(~K2 & !bKey2Pressed)
- {
-
- bKey2Pressed = 1;
-
- cKeyIn[0]=1;
- cKeyIn[1]=0x08;
- cKeyIn[2]=0;
- cKeyIn[3]=0;
- cKeyIn[4]=0;
- cKeyIn[5]=0;
- cKeyIn[6]=0;
- cKeyIn[6]=0;
- cKeyIn[8]=0;
-
- D12_WriteEndpoint(5,9,cKeyIn);
- }
- else if(K2 & bKey2Pressed)
- {
- bKey2Pressed = 0;
-
- cKeyIn[0]=1;
- cKeyIn[1]=0;
- cKeyIn[2]=0;
- cKeyIn[3]=0;
- cKeyIn[4]=0;
- cKeyIn[5]=0;
- cKeyIn[6]=0;
- cKeyIn[7]=0;
- cKeyIn[8]=0;
-
- D12_WriteEndpoint(5,9,cKeyIn);
- }
- }
- }
- }
实例中为了演示方便,没有加入按键消抖功能,实际应用中应加上。
从实例中可以看出,所有输入输出数据包都在最低字节位置插入了一个报告ID,有用数据都从第二个字节开始。
编译、烧录程序,插上设备,实际测试看看效果,再打开设备管理器,发现人体学输入设备里只多出了一个人体学输入设备(图中另一个是我本来的USB鼠标),在键盘和鼠标里都多了一个HID类型的键盘和鼠标,再分别查看它们的PID和VID,发现都是一样的。
|