STM32 JoystickMouse USB游戏杆鼠标的实现

本次程序的实现是基于上次CustomHID修稿过来的 , 工程的架构就不在介绍 , 这里主要介绍下 , 如何修改 。


首先当然是usb_desc.c的一些描述符了 。
设备描述符需要修改下bMaxPacketSize(最大包长度)为0x08个字节 , 因为该工程通讯的长度为4字节 , 根据USB洗衣规范 , 最大包长度只能是8、16、64等 , 所以这里选择0x08 , 这里要注意 , 改为0x08时 , 在usb_prop.c的DEVICE_PROP Device_Property->MaxPacketSize域也要改成0x08(我们在下面会说到) , 要跟配置描述符定义的最大包长度相同 , 否则 , 电脑上会出现:“此设备未识别”类似的提示 。最好还要修改下厂商ID和产品ID两项 。因为不修改PID和VID , 如果你上次CustomHID或其他USB工程也使用同样的PID和VID , 这次的工程 , 电脑不会重新加载新的驱动 , 可能会使功能无法实现 。如果出现上面的情况 , 只要打开设备管理器 , 找到对应的驱动设备 , 然后右键选择卸载 , 然后开发板重新上电 , 电脑的右下方就会跳出:发现新硬件 。还是贴出代码吧:
/* USB标准设备描述符*/
const uint8_t Joystick_DeviceDescriptor[JOYSTICK_SIZ_DEVICE_DESC] =
{
0x12,/*bLength:长度 , 设备描述符的长度为18字节*/
USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType:类型 , 设备描述符的编号是0x01*/
0x00,/*bcdUSB:所使用的USB版本为2.0*/
0x02,
0x00,/*bDeviceClass:设备所使用的类代码*/
0x00,/*bDeviceSubClass:设备所使用的子类代码*/
0x00,/*bDeviceProtocol:设备所使用的协议*/
0x08,/*bMaxPacketSize:最大包长度为64字节*/
0x88,/*idVendor:厂商ID为0x7788*/
0x66,
0x22,/*idProduct:产品ID为0x1122*/
0x11,
0x00,/*bcdDevice:设备的版本号为2.00*/
0x02,
1,/*iManufacturer:厂商字符串的索引*/
2,/*iProduct:产品字符串的索引*/
3,/*iSerialNumber:设备的序列号字符串索引*/
0x01/*bNumConfiguration:设备有1种配置*/
}; /* JoystickMouse设备描述符 */




接着需要修改配置描述符集 。配置描述符可以不需要修改 。找到接口的描述符的bNumEndpoints(该接口所使用的端点数)域 , 修改为0x01 , 表示使用1个端点 , nInterfaceProtocol (该接口使用的协议)域 , 修改成0x02 , 表示使用mouse协议 。HID描述符也不需要修改 。输入端点描述符跟CustomHID工程的一样 , 可以修改下 wMaxPacketSize(该端点支持的最大包长度)为0x04字节 , 因为这里只用到四个字节 , 注意这里的端点支持最大包长度可以不用按照USB的只能是8、16、64等规范 。接着删掉CustomHID工程中的的输出端点描述符 。代码如下:
/* USB配置描述符集合(配置、接口、端点、类、厂商)(Configuration, Interface, Endpoint, Class, Vendor */
const uint8_t Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =
{
0x09,/*bLength:长度 , 设备字符串的长度为9字节*/
USB_CONFIGURATION_DESCRIPTOR_TYPE, /*bDescriptorType:类型 , 配置描述符的类型编号为0x2*/
JOYSTICK_SIZ_CONFIG_DESC,/*wTotalLength:配置描述符的总长度为41字节*/
0x00,
0x01,/*bNumInterfaces:配置所支持的接口数量1个*/
0x01,/*bConfigurationValue:该配置的值*/
0x00,/*iConfiguration:该配置的字符串的索引值 , 该值为0表示没有字符串*/
0xE0,/* bmAttributes:设备的一些特性 , 0xc0表示自供电 , 不支持远程唤醒
D7:保留必须为1 , D6:是否自供电 , D5:是否支持远程唤醒 , D4~D0:保留设置为0*/
0x32,/*从总线上获得的最大电流为100mA */
//0x96,/*MaxPower:设备需要从总线上获取多少电流 , 单位为2mA , 0x96表示300mA*/


/************** 接口描述符****************/
/* 09 */
0x09,/*bLength:长度 , 接口描述符的长度为9字节 */
USB_INTERFACE_DESCRIPTOR_TYPE,/* bDescriptorType:接口描述符的类型为0x4 */
0x00,/*bInterfaceNumber:该接口的编号*/
0x00,/*bAlternateSetting:该接口的备用编号 */
0x01,/*bNumEndpoints:该接口所使用的端点数*/
0x03,/*bInterfaceClass该接口所使用的类为HID*/
0x01,/*bInterfaceSubClass:该接口所用的子类 1=BOOT, 0=no boot */
0x02,/*nInterfaceProtocol :该接口使用的协议0=none, 1=keyboard, 2=mouse */
0,/*iInterface: 该接口字符串的索引 */


/*****************HID描述符 ********************/
/* 18 */
0x09,/*bLength: HID描述符的长度为9字节 */
HID_DESCRIPTOR_TYPE, /* bDescriptorType: HID的描述符类型为0x21 */
0x10,/*bcdHID: HID协议的版本为1.1 */
0x01,
0x00,/*bCountryCode: 国家代号 */
0x01,/*bNumDescriptors: 下级描述符的数量*/
0x22,/*bDescriptorType:下级描述符的类型*/
JOYSTICK_SIZ_REPORT_DESC,/* wItemLength: 下一集描述符的长度*/
0x00,


/********************输入端点描述符******************/
/* 27 */
0x07,/* bLength: 端点描述符的长度为7字节*/
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType: 端点描述符的类型为0x21*/
0x81,/* bEndpointAddress: 该端点(输入)的地址,D7:0(OUT),1(IN),D6~D4:保留,D3~D0:端点号*/
0x03,/* bmAttributes: 端点的属性为为中断端点.
D0~D1表示传输类型:0(控制传输),1(等时传输),2(批量传输),3(中断传输)
非等时传输端点:D2~D7:保留为0
等时传输端点:
D2~D3表示同步的类型:0(无同步),1(异步),2(适配),3(同步)
D4~D5表示用途:0(数据端点),1(反馈端点),2(暗含反馈的数据端点),3(保留) , D6~D7:保留,*/
0x04,/* wMaxPacketSize: 该端点支持的最大包长度为4字节*/
0x00,
0x20,/* bInterval: 轮询间隔(32ms) */
/* 34 */
};
【STM32 JoystickMouse USB游戏杆鼠标的实现】



还要替换下报告描述符 , 该描述符定义了四个字节的输入数据域 , 第一个字节的D0位用来表示鼠标的左键 , D1为表示鼠标的D2键 , D3用来表示鼠标的中键(有些鼠标有的) , 其他5为保留 , 固定值为0 。第二数据域表示鼠标的X轴变化量 , 取值范围为-127~127 , 正的表示向上移 , 符的表示向下移 , 这里需要注意的是 , 这个值表示鼠标的变化量 , 而不是鼠标的位置 。第三个字节表示鼠标的Y轴的变化量 , 取值范围为-127~127 , 正值表示鼠标往上移 , 负值表示鼠标往下移 , 同样注意这个值是表示鼠标的变化量而不是鼠标的位置 。第四个值表示鼠标的滚轮的变化量 , 取值范围-127~127 , 正值表示向上滚 , 负值表示向下滚 , 同样注意是变化量 , 而不是位置 。代码如下:
/* HID的报告描述符*/
const uint8_t Joystick_ReportDescriptor[JOYSTICK_SIZ_REPORT_DESC] =
{
/*short ItemD7~D4:bTag;D3~D2:bType;D1~D0:bSize
**bTag ---主条目 1000:输入(Input) 1001:输出(Output) 1011:特性(Feature)1010:集合(Collection) 1100:关集合(End Collection)
** 全局条目 0000:用途页(Usage Page) 0001:逻辑最小值(Logical Minimum) 0010:逻辑最大值(Logical Maximum) 0011:物理最小值(Physical Minimum)
**0100:物理最大值(Physical Maximum) 0101:单元指数(Unit Exponet) 0110:单元(Unit) 0111:数据域大小(Report Size)
**1000:报告ID(Report ID) 1001:数据域数量(Report Count) 1010:压栈(Push) 1011:出栈(Pop) 1100~1111:保留(Reserved)
** 局部条目0000:用途(Usage) 0001:用途最小值(Usage Minimum) 0010:用途最大值(Usage Maximum) 0011:标识符索引(Designator Index)
**0100:

    推荐阅读