历史上的今天
今天是:2024年11月05日(星期二)
2020年11月05日 | STM32 JoystickMouse USB游戏杆鼠标的实现
2020-11-05 来源:eefocus
本次程序的实现是基于上次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 */
};
还要替换下报告描述符,该描述符定义了四个字节的输入数据域,第一个字节的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 Item D7~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:标识符最小值(Designator Minimum) 0101:标识符最大值(Designator Maximum) 0111:字符串索引(String Index) 1000:字符串最小值(String Minimum)
** 1001:字符串最大值(String Maximum) 1010:分隔符(Delimiter) 其他:保留(Reserved)
**bType---00:主条目(main) 01:全局条目(globle) 10:局部条目(local) 11:保留(reserved)
**bSize---00:0字节 01:1字节 10:2字节 11:4字节*/
//0x05:0000 01 01 这是全局条目,用途页选择为通用桌面
0x05,0x01, /*Usage Page(Generic Desktop)*/
//0x09:0000 10 01 这是个局部条目,用途为鼠标
0x09,0x02, /*Usage(Mouse)*/
//0xa1:0101 00 01 这是个主条目, 逻辑集合
0xA1,0x01, /*Collection(Logical)*/
//0x09:0000 10 01 这是个局部条目,用途为指针
0x09,0x01, /*Usage(Pointer)*/
/* 8 */
//0xa1:1010 00 01 这是个主条目,连接集合
0xA1,0x00, /*Collection(Linked)*/
//0x05:0000 01 01 这是全局条目,用途页选择为按钮
0x05,0x09, /*Usage Page(Buttons)*/
//0x19:0001 10 01 这是个局部条目,用途的最小值为1
0x19,0x01, /*Usage Minimum(1)*/
//0x29:0010 10 01 这是个局部条目,用途的最大值为3
0x29,0x03, /*Usage Maximum(3)*/
/* 16 */
//0x15:0001 01 01 这是全局条目,逻辑的最小值为0
0x15,0x00, /*Logical Minimum(0)*/
//0x25:0010 01 01 这是全局条目,逻辑的最大值为1
0x25,0x01, /*Logical Maximum(1)*/
//0x95:1001 01 01 这是全局条目,数据域的数量为3
0x95,0x03, /*Report Count(3)*/
//0x75:0111 01 01 这是全局条目,数据域的长度为1
0x75,0x01, /*Report Size(1)*/
/* 24 */
//0x81:1000 00 01 这是个主条目,有3*1bit数据域输入,属性为变量
0x81,0x02, /*Input(Variable)*/
//0x95:1001 01 01 这是全局条目,数据域的数量为1个
0x95,0x01, /*Report Count(1)*/
//0x75:0111 01 01 这是全局条目,每个数据域的长度为5bit
0x75,0x05, /*Report Size(5)*/
//0x81:1000 00 01 这是一个主条目,有1*5bit数据域输入,属性常量数组
0x81,0x03, /*Input(Constant,Array)*/
/* 32 */
//0x05:0000 01 01 这是全局条目,用途页为通用桌面
0x05,0x01, /*Usage Page(Generic Desktop)*/
//0x09:0000 10 01 这是个局部条目,用途为X轴
0x09,0x30, /*Usage(X axis)*/
//0x09:0000 10 01 这是个局部条目,用途为Y轴
史海拾趣
|
目前用ut6410想实现 radio的功能使用si47xx的模块 ut6410本身有提供i2c的接口和驱动 kernel linux2.6.24 硬件部份問題排除 有用示波器 sda sck脚位有讯号出来. 现在遇到的状况是想从user space透过i2c对si47xx丢cmd 但是write read回传都是-1 部 ...… 查看全部问答> |
|
背光代码 volatile S3C2440A_IOPORT_REG * v_pIOPregs= NULL; BOOL BacklightInitialize() { BOOL bRet = TRUE; BL_PowerOn(TRUE); & ...… 查看全部问答> |
|
msp430芯片RAM居然不能外扩??很郁闷,最近程序大了,需要大于2K的RAM了,可是msp430芯片RAM不能外扩,这个怎么办呢?课题做到一半,555555555555 谢谢各位,请出出主意!… 查看全部问答> |
|
TinyOS在MSP430F2618+CC2520平台上移植交流 目前TinyOS还仅支持MSP430低端的MCU比如f1611,以及CC2420等射频芯片。针对MSP430高端系列单片机,以及TI推出的第二代射频芯片CC2520还未能支持 前段时间把TinyOS移植到了上述平台上,基本功能都已经实现,针对无线协议栈还需要进一步优化!希望有 ...… 查看全部问答> |
|
CC2530串口中断接收的自定义缓存BUF最大可以定义多大? 我现在需要一个最少160字节的BUF存接收到的数据进行解析;但是定义buf[160]后用IAR编译总是提示IDATA空间不够;后来通过调节IAR-option -stack/heap 中的设置;但是最大也是只能设置到buf[135 ...… 查看全部问答> |
|
一般来说,七段数码管(也有称日字管)只能显示10个阿拉伯数字和部分英文字母,但是,按排列组合来算,七段数码管可以有128个组合,因此,就七段数码管可包含的信息量来说,显示26个字母加10个数字共36个字符是没问题的,只是人们没有建立一套显示 ...… 查看全部问答> |
|
做了块CC2500模块,模块发射数据很正常,但是接收的数据全部异常,找了两天了还没找到原因,程序问题已经排除(用别人的模块发射和接受都正常),请懂的人帮下小弟,小弟搞开始搞RF… 查看全部问答> |




