【STM32+cubemx】0017 HAL库开发:usb HID鼠标设备实现
Cubemx可以生成多种usb设备的初始化代码,本节我们就使用它来生成一个usb HID鼠标的工程,在开发板上运行以后,可以模拟usb鼠标的功能。
1)生成USB HID工程
仍然使用串口工程,如下图添加USB的配置:
可以看到,勾选usb device的功能后,右侧的芯片引脚已经设置好了,DP和DM两根线就是usb通信的差分线,使用了PA11和PA12引脚。
再配置USB的软件中间件,选择usb device,Human Interface Device Class,这个选项生成的就是usb鼠标工程。
修改时钟设置,把usb时钟设置为48M:
其他的配置都不用改,就可以生成工程代码了。
2)代码编写
打开生成的keil工程,可以看到已经生成了几个usb相关的源文件:
我们先来了解一下相关的代码,先打开usbd_hid.c这个源文件,找到其中定义的USBD_HID_CfgDesc数组,这里定义了hid设备的一些参数:
第161行定义了这是一个鼠标,第183行定义了数据发送的间隔为10ms。
间隔这个参数,也可以调用USBD_HID_GetPollingInterval这个函数获取,这个函数也在usbd_hid.c文件中定义。
(其他具体参数的定义比较复杂,可以学习一下usb的描述符后再解读)
接下来,我们需要了解的是USBD_HID_SendReport这个函数,也在usbd_hid.c中定义,它就是usb发送的函数,看以看到它内部调用了USB的发送函数,所以调用它就能把数据通过usb口发到上位机:
然后,我摸还需要知道鼠标传输数据的协议。鼠标发送的数据格式,一共四个字节:
第一个字节表示按键,bit0对应左键、bit1对应右键、bit3对应中键;0表示未按,1表示按下;
第二个字节表示x轴(即鼠标左右移动,0表示不动,正值表示往右移,负值表示往左移,范围-127~127,绝对值对应了移动量大小);
第三个字节表示y轴(即鼠标上下移动,0表示不动,正值表示往下移,负值表示往上移,范围-127~127,绝对值对应了移动量大小);
第四个字节表示鼠标滚轮(正值为往上滚动,负值为往下滚动,-127~127,绝对值对应了移动量大小)。
了解了以上这些必要的知识,我们就可以改写代码了,在主函数中添加,如下图所示:
先获取设备发送数据的间隔,保存,用作后面的延时使用;
再初始化X、Y方向的移动距离,要发送的数据保存在HID_Buffer数组中,然后就可以把数据发送出去了。
这一段代码实现的是,使鼠标按“左上<-->右下”的方式往复运动,运行距离为2。
编译、下载后,断电,再将开发板usb口连接到计算机上,就可以看到计算机识别出了一个新的鼠标设备,并且鼠标会自动来回运动。
注意观察一下设备的VID和PID,和cubemx的设置是一样的。
3)注意事项
a)usb hid设备的初始化
由于一般计算机都能识别HID设备,所以不用安装特殊的驱动程序也能够运行起来。但是需要注意的是,如果不断电重新插拔设备,可能会识别不到HID设备。
这是由于HID设备在初始插接到计算机上时,会同计算机进行几次交互,让计算机知道自己是个鼠标设备(或者键盘设备等等)、以及约定其他一些事项,之后才是向计算机发送数据。Cubemx生成的工程文件中,在初始化usb时,已经有这部分交互的代码了;所以我们在主循环中只需要发送鼠标的运动、点击等数据即可。
如果不断电,程序重新开始运行,计算机可能不会理会这些交互数据,会认为这是已有的usb设备在发送一般的通信数据,所以不能初始化成功。解决办法是在程序初始运行时,将usb的通信线拉低一下,让计算机认为有新设备插入,再去执行usb的初始化,这样就能顺利执行交互,让计算机识别出这是个鼠标设备。
增加的代码如下图,在初始化之前,把usb的IO口拉低一下( 使用USB_IO_rest()函数 ):
该函数具体实现如下:
添加这段代码后,只要程序重新执行,计算机就会认为有新的usb设备插入,会开始交互通信去识别设备的种类。
b)关于通信的时间间隔
主函数中,如图示的两行:
先获取usb设备的通信间隔,然后在主循环中,每延时这个间隔后,发送一次数据。
这个间隔是必须的,因为设备初始定义时包含了这个参数,会在和计算机的交互中确定设备的通信时间间隔;实际使用时,延时大于这个时间是可以的,但是小于这个时间会导致计算机端丢失数据。
好了,本节usb模拟HID鼠标的方法,就讲到这里了。
欢迎关注我的公众号,可留言“资料”获取相关资料和软件: