5859|15

156

帖子

1

TA的资源

一粒金砂(中级)

楼主
 

【STM32F769Discovery开发板试用】USB-HS HID收发简单测评 [复制链接]

 
 

       STM32的大部分评估板和第三方开发板都带有USB接口,USB接口配置为Device模式的话就可以跟电脑进行通信了,一般Device模式又分为HID/CDC/DFU/MS/Audio等协议,其中HID为人体学输入设备,CDC为虚拟串口设备,DFU为固件升级设备,MS为大容量存储设备,Audio为音频通信设备,HID适用于简单/低速的透传通信或是虚拟为鼠标键盘等人体学输入设备,可以自定义每个透传字段的长度,特征值等,不需要对数据包中的逐个字节进行解析;CDC适用于高速/大流量的透传通信,可以以winusb形式与电脑进行通信,不可以自定义透传字段特征值,只能从一帧数据包中逐个字节进行解析;DFU只适用于主控代码升级;MS只适用于将主控虚拟为U盘等存储设备;Audio只适用于将主控虚拟为声卡设备。在数据透传应用上,HID协议与CDC协议极其相似。
      官方给出的搭建HID代码例程的步骤非常简单,只需要使用CubeMX并配置发送字段即可完成,一步步开始吧,不过USB通信是需要固定48MHz时钟的,对于官方的评估板或者时钟设计参考官方评估板的第三方开发板,一般尽量使用CubeMX的板级初始化功能(即Access to Board Selector):

不使用芯片级初始化功能(Access to MCU Selector)意义在于,可以正确初始化USB时钟,避免不必要的麻烦。进入CubeMX引脚配置界面,将不必要的外设如ETH I2S SAI QSPI FMC LTDC等全部剔除,并设置USBHS(高速接口)为Device模式,外挂PHY,SOF不启用:

为什么是外挂PHY呢,很简单,看原理图和板子的芯片布局就知道了:

板子F769主控的USBHS接口是通过一块USB3320 USB-PHY芯片引出物理层microUSB接口的。

然后是对于USB Device第三方外设的配置,设置模式为Custom HID:

最后确认USB时钟频率为48MHz即可生成工程:

工程生成后,按照ST官方给出USBHID文档的指引,需要替换usbd_custom_hid_if.c文件下的CUSTOM_HID_ReportDesc_HS枚举数组:

#define REPORT_INPUT_LEN              64

__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_HS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
0x06,0xA0,0xFF,//用法页(FFA0h, vendor defined)
0x09, 0x01,//用法(vendor defined)
0xA1, 0x01,//集合(Application)
0x09, 0x02 ,//用法(vendor defined)
0xA1, 0x00,//集合(Physical)
0x06,0xA1,0xFF,//用法页(vendor defined)
	
//输入报告
0x09, 0x03 ,//用法(vendor defined)
0x09, 0x04,//用法(vendor defined)
0x15, 0x80,//逻辑最小值(0x80 or -128)
0x25, 0x7F,//逻辑最大值(0x7F or 127)
0x35, 0x00,//物理最小值(0)
0x45, 0xFF,//物理最大值(255)
0x75, 0x08,//报告长度Report size (8位)
0x95, REPORT_INPUT_LEN,
//报告数值
0x81, 0x02,
//输入(data, variable, absolute)

//输出报告
0x09, 0x05,
//用法(vendor defined)
0x09, 0x06,
//用法(vendor defined)
0x15, 0x80,
//逻辑最小值(0x80 or -128)
0x25, 0x7F,
//逻辑最大值(0x7F or 127)
0x35, 0x00,
//物理最小值(0)
0x45, 0xFF,
//物理最大值(255)
0x75, 0x08,
//报告长度(8位)
0x95, 0x40,
//报告数值(64 fields)
0x91, 0x02,
//输出(data, variable, absolute)
0xC0,
//集合结束(Physical)
0xC0
//集合结束(Application)  

};

这个数组会被初始化函数集USBD_CustomHID_fops_HS调用:

USBD_CUSTOM_HID_ItfTypeDef USBD_CustomHID_fops_HS =
{
  CUSTOM_HID_ReportDesc_HS,
  CUSTOM_HID_Init_HS,
  CUSTOM_HID_DeInit_HS,
  CUSTOM_HID_OutEvent_HS
};

然后修改usbd_conf.h的USBD_CUSTOM_HID_REPORT_DESC_SIZE,这里填52,即刚刚那个数组的长度:

添加回调函数,这步必不可少:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    HAL_IncTick();
}

上述代码修改完毕之后就可以用USBD_CUSTOM_HID_SendReport(&hUsbDeviceHS,buf,sizeof(buf));函数进行USBHID发送,每次调用函数发送的单位是64字节,固定的:

当然为了便于系统和HID软件识别,需要修改VID PID 设备名等参数:

#define USBD_VID     			1155
#define USBD_PID_HS     			22352
#define USBD_LANGID_STRING     		1033
#define USBD_MANUFACTURER_STRING     	"STMicroelectronics"


#define USBD_PRODUCT_STRING_HS     	"donatello1996 STM32F769 USBHID Device"
#define USBD_CONFIGURATION_STRING_HS  	"Custom HID Config"
#define USBD_INTERFACE_STRING_HS     	"Custom HID Interface"

最后使用示波器抓取发送函数耗时:
 

	while(1)
	{
		GPIOJ->BSRR |= 0x00000002;
		USBD_CUSTOM_HID_SendReport(&hUsbDeviceHS,buf,sizeof(buf));
		GPIOJ->BSRR |= 0x00020000;
		USBD_CUSTOM_HID_SendReport(&hUsbDeviceHS,buf,sizeof(buf));
	}

可以看出,即使是HID这种低速模式,发送间隔居然也缩小到不可思议的500ns,也就是1us可以发送128个字节,那么1s就可以发送128MB,在多数项目中绝对够用了,如果是使用高速的CDC模式则更快,1s发送几百MB不在话下。

最新回复

那你要怎么做到时钟翻转一次的时候写入64字节的数据呢,stm32的数据总线有64字节这么大的位宽吗     详情 回复 发表于 2024-1-5 11:41
点赞(1) 关注
 
 

回复
举报

156

帖子

1

TA的资源

一粒金砂(中级)

沙发
 

上传工程文件

1.zip

1.95 MB, 下载次数: 14

 
 
 

回复

1382

帖子

2

TA的资源

五彩晶圆(初级)

板凳
 

扯了,你这么用示波器抓只是判断 USBD_CUSTOM_HID_SendReport(&hUsbDeviceHS,buf,sizeof(buf)); 这个调用的间隔时间。

USB HS的接口 ULPI 的时钟才60MHz, 不可能有超过60MB/s的收发速度。

点评

时钟60MHz跟可以发送的数据量速率128MB/s有什么关系呢?60MHz只不过是USB时钟电平的频率,一秒钟内时钟可以翻转60M次,只要在时钟翻转一次电平的时候CPU往USBHS缓冲区送入一次64字节的数据包就代表发送成功了,接收  详情 回复 发表于 2020-8-4 18:13
 
 
 

回复

156

帖子

1

TA的资源

一粒金砂(中级)

4
 
cruelfox 发表于 2020-8-4 17:49 扯了,你这么用示波器抓只是判断 USBD_CUSTOM_HID_SendReport(&hUsbDeviceHS,buf,sizeof(buf)); 这 ...

时钟60MHz跟可以发送的数据量速率128MB/s有什么关系呢?60MHz只不过是USB时钟电平的频率,一秒钟内时钟可以翻转60M次,只要在时钟翻转一次电平的时候CPU往USBHS缓冲区送入一次64字节的数据包就代表发送成功了,接收端能否正常,准确无误接收这些数据包跟发送端有啥关系呢?

点评

你那只是函数返回而已,数据并没有发送出去。 HID报文是Interrupt Transfer类型的,只有主机polling的时候才可以把数据发出去。 这不是SPI... 就算是480Mbps的SPI,也最大才60MB/s的传输量。  详情 回复 发表于 2020-8-4 21:28
 
 
 

回复

1382

帖子

2

TA的资源

五彩晶圆(初级)

5
 
donatello1996 发表于 2020-8-4 18:13 时钟60MHz跟可以发送的数据量速率128MB/s有什么关系呢?60MHz只不过是USB时钟电平的频率,一秒钟内时钟可 ...

你那只是函数返回而已,数据并没有发送出去。

HID报文是Interrupt Transfer类型的,只有主机polling的时候才可以把数据发出去。

这不是SPI... 就算是480Mbps的SPI,也最大才60MB/s的传输量。

点评

数据有没有成功发送出去,需要电脑上位机那边接收并做计数,不是STM32这边需要关心的问题,先不说polling到底间隔多长,反正成功发送多少数据量肯定跟60MHz的时钟没有半毛钱关系。  详情 回复 发表于 2020-8-5 09:58
 
 
 

回复

156

帖子

1

TA的资源

一粒金砂(中级)

6
 
cruelfox 发表于 2020-8-4 21:28 你那只是函数返回而已,数据并没有发送出去。 HID报文是Interrupt Transfer类型的,只有主机polling的 ...

数据有没有成功发送出去,需要电脑上位机那边接收并做计数,不是STM32这边需要关心的问题,先不说polling到底间隔多长,反正成功发送多少数据量肯定跟60MHz的时钟没有半毛钱关系。

点评

是的,你认为的“发送成功”跟这没关系,USB模块存在不存在都没有关系。只要函数没有卡在那里就是成功。  详情 回复 发表于 2020-8-5 10:37
 
 
 

回复

1382

帖子

2

TA的资源

五彩晶圆(初级)

7
 
donatello1996 发表于 2020-8-5 09:58 数据有没有成功发送出去,需要电脑上位机那边接收并做计数,不是STM32这边需要关心的问题,先不说polling ...

是的,你认为的“发送成功”跟这没关系,USB模块存在不存在都没有关系。只要函数没有卡在那里就是成功。

 
 
 

回复

9803

帖子

24

TA的资源

版主

8
 

单从USB2.0的参数看,最大480Mbps即使不考虑协议最大速率不会超过60MB/S

你再去看USB3320的数据手册最大60MHz的时钟,它与STM32的总线宽度也只有1byte,所以它能和STM32的最大通信速率也不会超过60MH

 

 

点评

有图有真相,令人信服,点赞!既然官方手册都说了不超过60MB/s的话,那就肯定不会超过,但具体应该是多少数值我得写个上位机验证一下,这点是必须要实事求是的。我跟楼上那位争论的重点在于,不应该把USB时钟和每秒  详情 回复 发表于 2020-8-6 18:38
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

156

帖子

1

TA的资源

一粒金砂(中级)

9
 
littleshrimp 发表于 2020-8-6 17:37 单从USB2.0的参数看,最大480Mbps即使不考虑协议最大速率不会超过60MB/S 你再去看USB3320的数据手册最大 ...

有图有真相,令人信服,点赞!既然官方手册都说了不超过60MB/s的话,那就肯定不会超过,但具体应该是多少数值我得写个上位机验证一下,这点是必须要实事求是的。我跟楼上那位争论的重点在于,不应该把USB时钟和每秒发送数据量混在一起讨论,我认为这是两个完全不同的概念,发送数据量是跟USB时钟有很小的关联,但绝对不是简单的1对1关系,F769主控的USB控制器从USB时钟源获取工作时钟,在规定的周期内从缓冲区把一帧数据发出,那么一秒发送的数据量具体有多少,跟一帧数据大小和占用时钟周期有关系,这是一个二元关系,不是简单的1对1关系

点评

USBD_CUSTOM_HID_SendReport函数有返回值 你试一下,判断返回值为USBD_OK时再操作GPIO 测量一下波形看看间隔是多少 [attachimg]493267[/attachimg]  详情 回复 发表于 2020-8-6 19:54
 
 
 

回复

9803

帖子

24

TA的资源

版主

10
 
donatello1996 发表于 2020-8-6 18:38 有图有真相,令人信服,点赞!既然官方手册都说了不超过60MB/s的话,那就肯定不会超过,但具体应该是多少 ...

USBD_CUSTOM_HID_SendReport函数有返回值

你试一下,判断返回值为USBD_OK时再操作GPIO

测量一下波形看看间隔是多少

点评

好的,这周我有空试试,我也想知道F769的USBHID性能如何  详情 回复 发表于 2020-8-6 23:57
个人签名虾扯蛋,蛋扯虾,虾扯蛋扯虾
 
 
 

回复

7671

帖子

2

TA的资源

五彩晶圆(高级)

11
 

深挖的有点意思。

点评

道长见笑了  详情 回复 发表于 2020-8-6 23:57
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复

156

帖子

1

TA的资源

一粒金砂(中级)

12
 
littleshrimp 发表于 2020-8-6 19:54 USBD_CUSTOM_HID_SendReport函数有返回值 你试一下,判断返回值为USBD_OK时再操作GPIO 测量一下波 ...

好的,这周我有空试试,我也想知道F769的USBHID性能如何

 
 
 

回复

156

帖子

1

TA的资源

一粒金砂(中级)

13
 
freebsder 发表于 2020-8-6 22:02 深挖的有点意思。

道长见笑了

 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(中级)

14
 

博主对stm32的USB相关内容还是不是很了解啊

 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(中级)

15
 
donatello1996 发表于 2020-8-6 18:38 有图有真相,令人信服,点赞!既然官方手册都说了不超过60MB/s的话,那就肯定不会超过,但具体应该是多少 ...

发送的数据量和时钟频率是有很大关系的,时钟频率就决定了你IO口的翻转频率

 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(中级)

16
 
donatello1996 发表于 2020-8-4 18:13 时钟60MHz跟可以发送的数据量速率128MB/s有什么关系呢?60MHz只不过是USB时钟电平的频率,一秒钟内时钟可 ...

那你要怎么做到时钟翻转一次的时候写入64字节的数据呢,stm32的数据总线有64字节这么大的位宽吗

 

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表