历史上的今天
返回首页

历史上的今天

今天是: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轴

推荐阅读

史海拾趣

Gustav Klauke GmbH公司的发展小趣事

Gustav Klauke GmbH在电子行业中的五个发展故事

故事一:创立与电气时代的崛起

1879年,Gustav Klauke GmbH在德国雷姆沙伊德成立,正值第二次工业革命带来的“电气时代”大爆发。创始人Gustav Klauke凭借其对精工品质的执着追求,将公司的业务聚焦于电气连接技术和电缆作业工具的研发。随着全球电气工业的迅速发展,Klauke迅速成为该领域的佼佼者,为供电系统的各个环节提供可靠且实用的解决方案,满足了社会对电气产品日益增长的多元化需求。

故事二:产品创新与多元化发展

历经百年开拓,Klauke的产品线不断丰富和完善。从最初的钟表维修钳子,到电缆接线端子的生产,再到电池驱动的液压工具的研发,Klauke始终走在行业前沿。特别是1994年推出的首款电池驱动液压工具,标志着公司在电气连接技术上的重大突破。至今,Klauke已拥有多达280种工具,2000多个型号,超过10000个优质部件,广泛应用于电力、铁路和工业等多个领域。

故事三:品质与认证的国际认可

Klauke深知电气连接作业对安全可靠性的极高要求,因此始终将产品质量放在首位。公司不仅拥有IEC(国际电工委员会)、UL(美国保险商试验所)、DNV(挪威船级社)和GL(德国劳氏船级社)等特殊行业的权威资质认证,还通过严格的产品测试报告,确保每一款产品都能达到国际最高标准。这种对品质的坚持,让Klauke在全球客户中赢得了极高的信誉和口碑。

故事四:全球化布局与业务拓展

随着全球市场的不断扩大,Klauke积极实施全球化战略。从德国本土出发,公司在全球范围内设立了多个分公司和销售办事处,如印度、奥地利、西班牙等。同时,公司还通过并购和合作等方式,不断拓展业务领域和市场份额。例如,2018年Gustav Klauke GmbH被艾默生收购,现隶属于“专业工具”部门,这一举措进一步提升了公司在全球电气工具市场的竞争力。

故事五:未来展望与技术创新

面对未来,Klauke继续秉承德国精工品质的优良传统,致力于技术创新和服务优化。公司正密切关注物联网和工业4.0等下一代趋势,并制定相应的战略计划。例如,新型电池供电液压工具配备了蓝牙接口,实现了移动数据读取和工具配置的便捷性。此外,Klauke还计划推出更多高适应性、精准性的电气连接解决方案,以更好地满足全球日益多元的施工作业需求。展望未来,Klauke将继续向下一个百年目标迈进,为电子行业的发展贡献更多力量。

昭华(CHA)公司的发展小趣事

随着市场需求的不断变化,昭华公司敏锐地捕捉到了防水型轻触开关的市场潜力。他们投入大量资金进行技术研发,成功开发出了一系列防水性能优异、稳定性强的防水型轻触开关。这些产品一经推出便受到了市场的热烈欢迎,为昭华公司带来了可观的利润。此外,昭华公司还不断探索新的技术路线,成功将LED与开关结合,推出了发光开关系列产品,进一步丰富了公司的产品线。

Digilent公司的发展小趣事

在全球节能意识日益增强的背景下,DIALIGHT致力于推动绿色照明的发展。公司的LED产品具有高效节能、长寿命和环保等优点,有助于减少能源消耗和环境污染。此外,DIALIGHT还积极参与各种绿色照明项目,为推动可持续发展贡献自己的力量。

HTSEMI( Jin Yu Semiconductor )公司的发展小趣事

随着技术实力的不断提升,金宇半导体开始积极拓展国内外市场。公司制定了详细的市场拓展计划,通过参加国际电子展、举办技术研讨会等方式,加强与客户的沟通和交流。同时,金宇半导体还加大了品牌建设的力度,通过广告宣传、媒体合作等多种方式提升品牌知名度和美誉度。这些努力使得金宇半导体的市场份额逐年攀升,品牌影响力也日益增强。

Clulite公司的发展小趣事
  1. 创业初期
    • 描述Clulite公司的创始人或核心团队如何识别电子行业中的某个市场机遇。
    • 讲述他们是如何筹集初始资金,设立公司,并开发出第一款产品或解决方案的。
    • 可以提及公司在初创阶段面临的挑战,如技术难题、市场竞争等。
  2. 技术创新
    • 讲述Clulite如何通过研发创新,推出了一款颠覆性的产品或技术,从而获得了市场认可。
    • 详细描述这一创新过程,包括研发团队的努力、关键技术的突破等。
    • 提及这一创新如何帮助公司在市场上取得了竞争优势。
  3. 市场拓展
    • 描述Clulite如何逐步扩大市场份额,从地区市场走向全国乃至国际市场。
    • 可以讲述公司如何建立销售网络、与合作伙伴建立合作关系,以及参与行业展会等活动来推广品牌和产品。
    • 提及公司在市场拓展过程中遇到的挑战和应对策略。
  4. 品质管理
    • 讲述Clulite如何注重产品质量和客户体验,通过严格的质量控制流程来提升产品可靠性。
    • 描述公司如何建立完善的售后服务体系,为客户提供及时、专业的支持。
    • 提及这些举措如何帮助公司赢得了客户的信任和口碑。
  5. 可持续发展
    • 讲述Clulite如何关注环境保护和社会责任,推动公司的可持续发展。
    • 描述公司如何采取环保措施,减少生产过程中的污染排放。
    • 提及公司如何参与社会公益事业,回馈社会。

请注意,这些故事需要根据Clulite公司的实际情况进行调整和补充。如果你需要更具体的内容,建议查阅Clulite公司的官方网站、新闻报道或行业分析报告,以获取更详细的信息和数据。

Hi-Tron Semiconductor Corp公司的发展小趣事

机顶盒,全称为数字视频变换盒,是现代家庭娱乐中不可或缺的重要设备。从广义上讲,任何与电视机连接的网络终端设备均可视为机顶盒,其发展历程涵盖了从模拟频道增补器到数字卫星、地面及有线电视机顶盒的广泛范畴。而从狭义角度看,机顶盒特指那些具备数字处理能力的设备,如IPTV机顶盒、DVB-S卫星机顶盒、DVB-T地面机顶盒及DVB-C有线电视机顶盒等。

机顶盒的核心功能在于接收并转换数字电视信号,使之能在传统或智能电视上播放。它不仅能接收来自有线电缆、卫星天线及宽带网络的信号,还能提供电子节目指南、网页浏览等增值服务。通过机顶盒,用户能够享受到高清乃至4K超高清的电视节目,体验更为细腻的画面和震撼的音效。此外,机顶盒还具备网络交互能力,支持在线购物、观看网络视频、玩游戏等多元化活动,使电视机从单向接收信息的设备转变为智能互动终端。

随着技术的不断进步,机顶盒正朝着高清化、智能化方向发展。未来,机顶盒将不仅限于基本的信号接收与解码功能,还将融入更多智能推荐、语音识别等先进技术,为用户提供更加个性化、便捷的娱乐体验。总之,机顶盒作为连接电视与互联网的桥梁,正以其丰富的功能和广泛的应用场景,不断满足用户日益增长的娱乐需求。

问答坊 | AI 解惑

LCD的一点资料

本帖最后由 paulhyde 于 2014-9-15 08:54 编辑 大家好 这是我收集到的一些LCD的资料 希望对大家有用!  …

查看全部问答>

linux下i2c控制radio的问题

目前用ut6410想实现 radio的功能使用si47xx的模块 ut6410本身有提供i2c的接口和驱动 kernel linux2.6.24 硬件部份問題排除 有用示波器 sda sck脚位有讯号出来. 现在遇到的状况是想从user space透过i2c对si47xx丢cmd 但是write read回传都是-1 部 ...…

查看全部问答>

wince5.0 2440背光问题

背光代码 volatile S3C2440A_IOPORT_REG * v_pIOPregs= NULL; BOOL BacklightInitialize() {     BOOL    bRet = TRUE;     BL_PowerOn(TRUE);               & ...…

查看全部问答>

第三方控件如何部署到wince中,在运行时提示无法找到第三方控件的dll

第三方控件如何部署到wince中 在运行时提示无法找到第三方控件的dll…

查看全部问答>

晶振运行正常吗?

我用示波器测量了一下F149的PIN9,X1OUT波形,有一个在2V范围,幅度在0。2V左右的锯齿波,频率有26US左右。而在PIN52,X2OUT上没有波形。我LXT1上接得是32678HZ的晶振,X2上接得是8M晶振。 请问这样状态正常吗?…

查看全部问答>

【求助】msp430芯片RAM居然不能外扩??

msp430芯片RAM居然不能外扩??很郁闷,最近程序大了,需要大于2K的RAM了,可是msp430芯片RAM不能外扩,这个怎么办呢?课题做到一半,555555555555 谢谢各位,请出出主意!…

查看全部问答>

TinyOS在MSP430F2618+CC2520平台上移植交流

目前TinyOS还仅支持MSP430低端的MCU比如f1611,以及CC2420等射频芯片。针对MSP430高端系列单片机,以及TI推出的第二代射频芯片CC2520还未能支持 前段时间把TinyOS移植到了上述平台上,基本功能都已经实现,针对无线协议栈还需要进一步优化!希望有 ...…

查看全部问答>

关于CC2530串口中断接收的问题

CC2530串口中断接收的自定义缓存BUF最大可以定义多大? 我现在需要一个最少160字节的BUF存接收到的数据进行解析;但是定义buf[160]后用IAR编译总是提示IDATA空间不够;后来通过调节IAR-option -stack/heap 中的设置;但是最大也是只能设置到buf[135 ...…

查看全部问答>

用七段数码管显示26个字母的方案

一般来说,七段数码管(也有称日字管)只能显示10个阿拉伯数字和部分英文字母,但是,按排列组合来算,七段数码管可以有128个组合,因此,就七段数码管可包含的信息量来说,显示26个字母加10个数字共36个字符是没问题的,只是人们没有建立一套显示 ...…

查看全部问答>

CC2500发射很正常,但是接收的数据异常

做了块CC2500模块,模块发射数据很正常,但是接收的数据全部异常,找了两天了还没找到原因,程序问题已经排除(用别人的模块发射和接受都正常),请懂的人帮下小弟,小弟搞开始搞RF…

查看全部问答>