一步步实现stm32cube的usb之CUSTOM_HID当串口使用 (stm32F407discoery板)
每次用串口调试感觉麻烦死了,尤其是电脑上没有串口,usb转串口线一大坨
为什么用usb 的 hid 功能?
hid 是免驱的,任何电脑上都内置的有他的驱动.
插上去就可以用.
对于调试来说,hid的最大速度64k/s完全够用了,但是,这个速度是理论的,实际中根本不可能达到!!
但是缩减下,能达到串口的115200bit/s就比串口好用了.
记录开始:
首先上配置:
我的板卡是stm32f407discovery板,晶振8M
led是PD12/PD13
按键是PA0
首先选中外部时钟,然后去时钟界面输入外部时钟为8M
选中usb 的fs模式, 选择custom hid接口功能
然后去打开usb_fs配置 ,其实就是默认的
中断号配置界面
usb device配置图
usb 端口描述图
还有led的IO口设置,这个就不再描述了.
这样配置结束了,然后生成工程,打开,编译!
为什么用usb 的 hid 功能?
hid 是免驱的,任何电脑上都内置的有他的驱动.
插上去就可以用.
对于调试来说,hid的最大速度64k/s完全够用了,但是,这个速度是理论的,实际中根本不可能达到!!
但是缩减下,能达到串口的115200bit/s就比串口好用了.
记录开始:
首先上配置:
我的板卡是stm32f407discovery板,晶振8M
led是PD12/PD13
按键是PA0
首先选中外部时钟,然后去时钟界面输入外部时钟为8M
选中usb 的fs模式, 选择custom hid接口功能
然后去打开usb_fs配置 ,其实就是默认的
中断号配置界面
usb device配置图
usb 端口描述图
还有led的IO口设置,这个就不再描述了.
这样配置结束了,然后生成工程,打开,编译!
38 个回复
admin
赞同来自:
另外, 这个完整的工程幸好以前都放到百度网盘了, 我刚把它移动到了论坛的专用百度网盘里了,
现在可以去下载测试了 , 这个工程的名字: Hid_USB(实现hid当串口使用程序).7z
需要的去 http://pan.baidu.com/s/1gdhcja7 里面找
admin
赞同来自: zzt_car 、热血熊
看到设备管理器里面有个叹号,这个不用着急,因为咱们还没有配置端点造成的.
就是上面这个地方,
我是准备让他弄成串口类似的功能,所以不想定义什么乱七八糟的id
直接用数组写和读,然后接收后用自己定的协议来处理
所以,我参考网上的帖子对这个描述的例子,代码如下:
我也不知道会不会又被编辑器吞代码,所以,上图
查看这个函数的数组长度定义,改为33
如果你不知道怎么查看,就去看usbd_conf.h里面修改吧.
这个时候再进行编译,烧录到板子.
这个时候可以看到设备管理器里面的hid已经多了两个
HID-compliant device 和 usb 输入设备
admin
赞同来自:
系统完成了这么多,
只有这个事用户可以操作的,其他的就是系统完成usb的对接的
所以去查看下这个定义
USBD_CustomHID_fops_FS
里面有刚才写的报告描述符函数
有通过hid实现其他工程用的初始化函数
有一个通过hid实现其他工程用的失能函数
还有通过hid控制一个貌似叫输出事件的函数
一步一步来,先来看看这个输出事件是怎么回事?
于是直接在工程中查找名字叫CUSTOM_HID_OutEvent_FS 的位置,
发现貌似没有什么值得注意的被调用的地方,所以初步判断这个应该是利用了其他方法调用的,比如:指针
但是尽管事其他类似指针的调用,也要找出来,要不然不知道这个东西怎么用啊,
回到MX_USB_DEVICE_Init这个函数,
我们查看下USBD_CUSTOM_HID这个定义
于是我找到了它
看到里面的
USBD_CUSTOM_HID_DataOut
和
USBD_CUSTOM_HID_DataIn
,从名称可以看出来,这个就是数据处理的地方了.
去查看OUT的函数
可以看到,从usb获取的数据,利用
USBD_CUSTOM_HID_ItfTypeDef
这个函数指针进行了一系列的处理
其中的这句话
说明我们准备用的这个函数
这个里面的事件和状态都是来自此处的buf[0]和buf[1]
于是,我可以这样测试一下,我写个代码在
CUSTOM_HID_OutEvent_FS这个函数里
上面的意思是如果PC端的hid上位机发送0x00 0x05 那么PD12的led进行反转
如果发送的是0x00 0x06 那么PD13的led进行反转
这样就可以测试.hid是不是可用了.
于是我进行了烧录,和测试
结果表明确实可以控制板子上面的led的亮灭,不过,感觉不是实时的,总有些延时在里面,
判断是usb的hid方面利用的是poll查询发送模式,所以,可以修改这个查询的时间,
我们打开,工程中的 usbd_customhid.c 文件
找到控制时间的变量,改为 0x01 即1ms
再次烧录,现在基本感觉不出有任何动作延时了..
未完待续!
admin
赞同来自: icebin 、热血熊
透过上面的
这个函数的构造,
我们只能得到两个字节的数据使用,那么我们有方式把更多的字节取出来用吗?而不用对底层的usb打动干戈?
猜想可以定义一个类似下面的代码函数
利用指针把需要的数据都取出来,然后处理啥的都可以自己随便弄了
我们要是准备这么用肯定要把这个函数注册到包含
CUSTOM_HID_OutEvent_FS()这个函数的结构体里面去.
由上面我们知道这个函数是在
USBD_CustomHID_fops_FS()
里面注册的,所以我们要再这个函数结构体里面进行添加
这样我们初始化usb的时候,这个函数就注册到usb里面了,
但是它是由
USBD_CUSTOM_HID_ItfTypeDef来定义的结构体,所以我们也需要在这个定义里添加
但是还不够,我们并没有在usb的底层程序里调用,
我们找到上面楼层里提到的USBD_CUSTOM_HID_DataOut()这个函数
这个函数在usbd_customhid.c 文件里
函数的原型是:
我们准备再这个里进行调用,就在那些buf[0]和buf[1]之后一行.添加
这样当usb接收到数据,就会利用函数指针调用,我们添加的函数进行各种操作了
例如下面的测试代码:
我们取出usb的数据传递给了一个数组,利用数组可以进行一系列的数据处理了.
这个楼层只是我的猜想,还没有进行验证,明天去验证一下.
admin
赞同来自:
假定我们发送一个64字节数据通过hid,
通过keil查看Buff这个内存地址,可以看到内存的数据和发送完全一致!
那么hid的数据接收方面就测试完毕!
admin
赞同来自: zhouzhi666 、秦时明月wqq 、hant_9
在文件 usbd_custom_hid_if.c中最后一行
我们就可以调用这个发送字节到pc了.
为了测试方便,同时懒省事,我将楼上CUSTOM_HID_OutBuffEvent_FS 这个刚刚添加的修改下
意思是接收到数据之后返回接收到数据的前三个字节.
当然实际使用中,你可以定义一个协议,这样就知道需要返回多少长度的字节了.
ok,hid的初步使用介绍完了.
希望能帮到看到此贴的人,
同时希望大家踊跃分享自己的心得和体会.
无色旋律
赞同来自:
一毛
赞同来自:
cnnblike
赞同来自:
还有polling interval那个修改成1ms就行了
twlkengi
赞同来自:
赵振林 - 90后,,,
赞同来自: icebin
老板交给一个USB任务,以前也没接触过,各种资料各种看,最后搞得晕晕乎乎的,跟着大神走了一遍,看见被电脑识别的那一刻,好吧,我承认自己激动了。
icebin
赞同来自:
讲的非常好,太实用了
admin
赞同来自:
总结:
共修改了四个文件,如果你害怕每次生成的时候把修改好的程序给弄没了,那么,你可以直接复制并替换这四个文件即可.
yujunmolu
赞同来自:
latera
赞同来自:
太好了,学习中
fearless
赞同来自:
如果是自己写上位机实现读取数据,该怎么处理呢?
在网上找了很多winform的程序都没成功
乌龟也会飞
赞同来自:
打什么 为什么我照着你的流程走了一遍然后使用USBHIDdemonstrator来通信不成功啊
Playnetics
赞同来自:
能不能附加上完整代码?我这边照做,发现后面几步多字节通讯的代码就完全没有了注释,或者解释的就不详细了,比如:
这个函数的定义,创建和调用我不知道是怎么样的关系,另外我看到64个字节的保存,我不清楚是不是漏写了?
static int8_t CUSTOM_HID_OutDulBuf_FS (uint8_t* DulBuf)
{
uint8_t outdata[64];
outdata[0] = *(DulBuf++);
outdata[1] = *(DulBuf++);
outdata[2] = *(DulBuf++);
outdata[3] = *(DulBuf++);
//请问这里是不是还要一直做到outdata[63]? 另外下面这个判断延时有什么作用吗?
if(outdata[0] != 3)
HAL_Delay(100);
return (0);
}
我之前调过USB_CDC的通讯,但是因为安装驱动程序的问题,搞的头大,因为客户的机器各不相同,特别是win64位的程序,安装驱动要强制签名,然后有的版本USB驱动内核又不完整,很头疼;
一直想搞这个HID的,一直搞不懂,这篇写的比较详细,但是缺点是后面的说明比较省了,不如前面的讲的那么详细,希望能把以上的问题帮我说一下,感谢!
admin
赞同来自: Music King
@Playnetics
函数的创建和调用你要去看 [大晚上,睡不着,再更新一点吧] 这层楼,
大致意思是:
首先要去usb库函数的USBD_CUSTOM_HID_ItfTypeDef 里面定义一个outdulBuf接收事件函数指针,
然后去USBD_CustomHID_fops_FS函数里将这个指针实体化 ,
这些都做完之后, 就去usb接收函数里注册这个事件,使这个事件和usb数据接收联系起来, 于是需要在USBD_CUSTOM_HID_DataOut()这个函数里注册,
这个函数里原来就有一个注册事件
((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutEvent(hhid->Report_buf[0],
hhid->Report_buf[1]);
这个事件对应的是int8_t (* OutEvent) (uint8_t, uint8_t );
,实体函数是CUSTOM_HID_OutEvent_FS,
那么我就复制这个事件, 让它重新注册到我刚刚自定义的
((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutDulBuf(hhid->Report_buf);
, 这样接收到数据后,我自定义的函数就也能接收到数据, 然后我在自定义的函数里就可以随便怎么去处理数据了
你看下面的箭头的顺序捋捋吧
而, 注册事件的函数里, 你注意下面
我是参照原来的写的,原来的只是返回[0]和[1]的数据,我直接自定义返回所有接收到的数组指针...
admin
赞同来自:
@Playnetics
至于你说的://请问这里是不是还要一直做到outdata[63]? 另外下面这个判断延时有什么作用吗?
我定义这个outdata[64]只是为了验证是不是真的接收到我pc机发送下来的数据, 通过这个变量在keil里就可以直观看到接收到的数据......还有那个延时没有用, 应该是我之前测试其他的时候留下的忘了删......
Playnetics
赞同来自:
非常感谢,收到,今天按照这个做了一下,发现有时候电脑能识别到 HID设备,但是有时候又无法正确识别,感觉怎么不可靠呢?
无法正确识别的情况会在电脑设备管理器下面的<通用串行总线控制器>下面显示一个 unkonow USB device;
不清楚这个会是啥问题呢 ?
另外我看了上面回复的,我还是没看到使用这个
Playnetics
赞同来自:
但我想是不是版主有误写啊?上面这个函数和下面这个函数有什么关系吗?是怎么样定义调用关系的呢 ?
static int8_t CUSTOM_HID_OutDulBuf_FS (uint8_t* DulBuf)
另外我已经定义了结构体
和添加代码到
并添加了函数 :
static int8_t CUSTOM_HID_OutDulBuf_FS (uint8_t* DulBuf)
{
uint8_t outdata[64];
outdata[0] = *(DulBuf++);
outdata[1] = *(DulBuf++);
outdata[2] = *(DulBuf++);
outdata[3] = *(DulBuf++);
if(outdata[0] != 3)
HAL_Delay(100);
return (0);
}
但是现在就是不知道最上面说的那个函数该怎么添加?
如果可以的话,希望能对下面这个函数说一下?
Playnetics
赞同来自:
经过我的初步实验,我发现
有点累
赞同来自:
你好,在网盘中用的历程,显示“未知设备”,系统时钟配置的是168M,USB时钟48M
gx_9988
赞同来自:
梦回庄周
赞同来自:
请问按照步骤烧入后出现未知USB设备怎么回事?
hklevejkl
赞同来自:
dgq
赞同来自: 飘风磊落
写得很好,能提供合作吗?帮我做一个小系统。用stm32f105来实现PC通信与U盘读写。麻烦联系我1035026591@qq.com
dgq
赞同来自:
根据本文的指导,本人顺利完成了项目。在此表示感谢!
吉米
赞同来自:
感谢分享,很有帮助。
ˇ北岸星空…
赞同来自:
赞
ImpulseHu
赞同来自:
stm32f103c8t6按楼主的方法试了下,可以使用上位机向USB发送数据来控制我的PC13口LED。感谢!!!
沉成林
赞同来自:
f407zg按方法操作,发送数据之后卡死了
cai_stm32cube - 85 电源 微控
赞同来自:
最近也在摸索HID通信,B站有个手把手教学的也挺实用。我自己用F103C8试了一下,当端点的最大包长超过8后,接收和发送的数据都会有问题,可是如果端点长度太小速度又太慢,不知道大家有没有这样的问题。F103只能支持到全速(FS)模式。
微微阳光
赞同来自:
USB调试软件能否给个下载链接
yzz163
赞同来自:
谢谢,注册事件那段,将的很好。
staunchheart
赞同来自:
设备有收到PC发过来的数据,但设备的回复
USBD_CUSTOM_HID_SendReport_FS(Buff,3);
PC端没有收到,有朋友试成功了吗?
staunchheart
赞同来自:
补充说明,从单片机发送到电脑本身没有问题,但不能在CUSTOM_HID_OutBuffEvent_FS
这些接收的方法中去发送,这种发送,电脑会收不到,而且频繁调用还会使PC端的程序卡死,如上面朋友哪样。
只能在main中发送,发奇怪的问题。
有什么解决方案吗?收到数据后,如果要执行完后就返回如何处理。