近来一直研究USB,刚开始确实有些困难,不过贵在坚持。手头主要一本《圈圈教你玩USB》,看到自定义USB部分,就想在原子开发板上实现HID。其实在开发板例程—— 触控USB鼠标实验基础上还是比较容易改动的。下面简单总结一下改动步骤:
1、修改设备描述符
在文件usb_desc.c中。因为鼠标本身就属于HID设备,因此,改动起来就相当容易了。设备描述符即Joystick_DeviceDescriptor[]基本不用改动,但最好把idVendor、idProduct字段改下,这样有助于PC重新为设备查找驱动程序,至于改成什么值就随意了。这里我将它们改为如下值:
0x88, /*idVendor (0x8888)*/
0x88,
0x06, /*idProduct = 0x0006*/
0x00,
当然,这是圈圈书中取得值,由于历史原因(USB技术规范文件上就有这句话,感觉很神秘的样子啊~),我这里只是为了图方便就采用这俩值。如果修改了USB固件,这里最好也顺便把这俩值修改下,便于PC重新为设备加载驱动。
2、修改配置描述符
在Joystick_ConfigDescriptor[]中,将接口描述符部分bInterfaceSubClass和nInterfaceProtocol字段改为都改为0x00,这样就表示是自定义的HID设备了,需要我们自己编写上位机进行数据的接收和发送。两个字段的修改:
0x00, /*bInterfaceSubClass: 1=BOOT, 0=no boot*/
0x00, /*nInterfaceProtocol: 0=none, 1=keyboard, 2=mouse*/
在端点描述符部分,将wMaxPacketSize字段改为0x10,0x00,即表示端点1最大包长度为16字节。因为原来原子板鼠标例程用的是中断输入端点1,这里就顺便用这个端点好了。端点最大包长度修改:
0x10, /*wMaxPacketSize: 16 Byte max */
0x00,
配置描述符中其他部分不用改动。
3、修改报告描述符
这里我将圈圈书中的报告描述符直接搬过来,为了简单起见,将描述符中输出数据描述部分去掉。然后将报告描述符的长度JOYSTICK_SIZ_REPORT_DESC改为21,即报告描述符共21个字节。
#define JOYSTICK_SIZ_REPORT_DESC 21
这里报告描述符定义了8个输入字节。将报告描述符贴在这里:
//每行开始的第一字节为该条目的前缀,前缀的格式为:
//D7~D4:bTag。D3~D2:bType;D1~D0:bSize。以下分别对每个条目注释。
//这是一个全局(bType为1)条目,将用途页选择为普通桌面Generic Desktop  age。
//后面跟1字节数据(bSize为1),后面的字节数就不注释了,自己根据bSize来判断。
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
//这是一个局部(bType为2)条目,用途选择为0x00。在普通桌面页中,
//该用途是未定义的,如果使用该用途来开集合,那么系统将不会把它
//当作标准系统设备,从而就成了一个用户自定义的HID设备。
0x09, 0x00, // USAGE (0)
//这是一个主条目(bType为0)条目,开集合,后面跟的数据0x01表示
//该集合是一个应用集合。它的性质在前面由用途页和用途定义为
//用户自定义。
0xa1, 0x01, // COLLECTION (Application)
//这是一个全局条目,说明逻辑值最小值为0。
0x15, 0x00, // LOGICAL_MINIMUM (0)
//这是一个全局条目,说明逻辑值最大为255。
0x25, 0xff, // LOGICAL_MAXIMUM (255)
//这是一个局部条目,说明用途的最小值为1。
0x19, 0x01, // USAGE_MINIMUM (1)
//这是一个局部条目,说明用途的最大值8。
0x29, 0x08, // USAGE_MAXIMUM (8)
//这是一个全局条目,说明数据域的数量为八个。
0x95, 0x08, // REPORT_COUNT (8)
//这是一个全局条目,说明每个数据域的长度为8bit,即1字节。
0x75, 0x08, // REPORT_SIZE (8)
//这是一个主条目,说明有8个长度为8bit的数据域做为输入。
0x81, 0x02, // INPUT (Data,Var,Abs)
//下面这个主条目用来关闭前面的集合。bSize为0,所以后面没数据。
0xc0 // END_COLLECTION
4、修改端点1发送字节数
在usb_prop.c中,找到Joystick_Reset()函数,将其中SetEPTxCount(ENDP1, 4);改为SetEPTxCount(ENDP1, 8);,因为报告描述符定义的是8个输入字节。
5、修改Joystick_Send()函数
Joystic_Send()函数在hw_config.c文件中。原来的Joystick_Send()函数发送4个字节,这里将其改为发送8个字节:
void Joystick_Send(u8 buf0,u8 buf1,u8 buf2,u8 buf3, u8 buf4, u8 buf5, u8 buf6, u8 buf7)
{
u8 Mouse_Buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
/* prepare buffer to send */
Mouse_Buffer[0]=buf0;
Mouse_Buffer[1]=buf1;
Mouse_Buffer[2]=buf2;
Mouse_Buffer[3]=buf3;
Mouse_Buffer[4] = buf4;
Mouse_Buffer[5] = buf5;
Mouse_Buffer[6] = buf6;
Mouse_Buffer[7] = buf7;
/*copy mouse position info in ENDP1 Tx  acket Memory Area*/
UserToPMABufferCopy(Mouse_Buffer, GetEPTxAddr(ENDP1), 8);
/* enable endpoint for transmission */
SetEPTxValid(ENDP1);
}
还有,千万别忘了在hw_config.h中修改Joystick_Send()的声明,否则keil将报错的,当然,等报错的时候也就意识到还木有修改了~
6、经上述步骤,其实已经差不多了,在main()中,简单修改如下:
while(1)
{
key=KEY_Scan(1);//支持连按
if(key)
{
if(key==KEY_UP)Joystick_Send(11, 22,33,44,55,66, 77, 88); //发送滚轮数据到电脑
}
if(bDeviceState==CONFIGURED){
LED1=0;//当USB配置成功了,LED1亮,否则,灭
}else{
LED1=1;
}
}
当我们按动原子旗舰板上的KEY_UP键,就可以向PC发送数据了。打开圈圈写的HID上位机,看下效果
怎样,是不是收到数据了啊~注意PVN改为0200啊,因为我们USB固件中用的是USB2.0,当然,将USB版本改为1.0也是可以的,只要和上位机中PVN一致就可以了。
|