STM32H743集成了高速USB 2.0 OTGOn-The-Go外设支持Host主机、Device设备、OTG双模三种模式兼容USB 1.1低速/全速12Mbps。USB是嵌入式系统中实现与PC/外设数据交互的核心接口可实现U盘读写、虚拟串口、USB摄像头、自定义HID设备等功能。一、STM32H743 USB 核心硬件特性STM32H743的USB OTG外设分为USB_OTG_FS全速12Mbps和USB_OTG_HS高速480Mbps其中HS可兼容FS模式核心特性如下特性说明传输速率低速1.5Mbps、全速12Mbps、高速480Mbps需外加PHY工作模式Device设备如虚拟串口、U盘、HID键盘Host主机读写U盘、连接USB外设OTG双模切换接口类型USB_OTG_FSDPA12、D-PA11、VBUSPA9、IDPA10传输方式批量传输Bulk、中断传输Interrupt、同步传输Isochronous、控制传输Control硬件加速内置DMA控制器支持高速数据传输降低CPU占用电源管理支持VBUS检测Host模式、软/硬件电源控制协议兼容USB 2.0规范支持CDC虚拟串口、MSC大容量存储U盘、HID人机交互、自定义类典型应用虚拟串口CDC、USB U盘MSC、USB转CAN、自定义HID设备、USB数据采集USB 核心信号信号名称功能典型引脚STM32H743备注USB_DP差分数据线PA12OTG_HS/FSUSB_DM差分数据-线PA11OTG_HS/FSUSB_VBUS总线电压检测PA9OTG_HSHost模式下检测外设是否接入Device模式下检测供电USB_IDOTG模式识别PA10OTG_HS区分Host/Device模式接地Host悬空Device注Device模式D需接1.5kΩ上拉电阻全速/高速D-接1.5kΩ上拉低速Host模式需外接5V电源给USB外设供电如U盘并检测VBUS电平二、USB 工作原理USB通信的核心是“主机Host发起请求设备Device响应”STM32可作为Host或Device核心概念和流程如下1. 核心概念端点EndpointUSB设备的通信端口每个端点对应一种传输类型控制端点Endpoint 0所有设备必备用于设备枚举、配置批量端点Bulk用于大量数据传输如U盘、虚拟串口容错重传中断端点Interrupt用于小数据高频传输如HID键盘、鼠标同步端点Isochronous用于实时数据传输如音频、视频不重传。枚举EnumerationDevice接入Host后Host通过控制端点获取设备信息厂商ID、产品ID、设备类并分配地址的过程。STM32库已经将最复杂的枚举编写完成可以不关注。USB类Class标准化的设备类型无需自定义驱动CDC通信设备类虚拟串口PC端识别为COM口MSC大容量存储类U盘PC端识别为可移动磁盘HID人机交互类键盘、鼠标免驱自定义类需编写专用驱动。2.报告描述符报告描述符report descriptor是用来描述一个报告的结构以及该报告里的数据是用来干什么的。通过报告描述符USB 主机可以分析出报告里的数据所表示的意义。USB HID 报告描述符Report Descriptor组成报告描述符由若干Item条目 / 项拼接而成每个 Item 用来描述一项属性Item 分为短 ItemShort Item绝大多数场景使用和极少用的长 ItemLong ItemMain 主条目bType0定义报告数据本身是最终生效的描述项用来定义输入 / 输出 / 特征数据。Input(0x81)设备发给主机的数据鼠标坐标、按键Output(0x91)主机下发给设备的数据LED 灯控Feature(0xB1)配置类双向数据设备参数读写Collection(0xA1)集合起始用于分组描述一组相关控件End Collection(0xC0)集合结束Global 全局条目bType1全局作用域在重置前一直有效定义数据的公共属性。Usage Page(0x05)用途页选择功能分类通用桌面、按键、游戏设备Logical Minimum/Maximum(0x15/0x25)逻辑值范围Physical Minimum/Maximum(0x35/0x45)物理值范围Report Size(0x75)每个数据域的 bit 位数Report Count(0x95)数据域的个数Unit/Unit Exponent单位与单位指数Report ID(0x85)报告 ID多报告时区分不同报告Local 局部条目bType2仅对下一个 Main 条目生效描述控件的局部属性。Usage(0x09)当前控件的具体用途X 轴、左键Usage Minimum / Usage Maximum(0x19/0x29)用途范围批量描述多个控件Designator Index物理指示器索引String Index字符串描述索引使用函数USBD_HID_SendReport(hUsbDeviceFS,(uint8_t*)MouseData,sizeof(MouseData));将描述符发送给主机。应用程序memcpy(MouseDataT, MouseData, sizeof(MouseData)); key KEY_Scan(1); switch(key) { case KEY0_PRES: MouseData[0] | 0x01; break; case KEY1_PRES: MouseData[1] 21; break; case WKUP_PRES: MouseData[3] -12; break; default: MouseData[0] 0; MouseData[1] 0; MouseData[2] 0; MouseData[3] 0; } //如果有变化发送 if(MouseData[0]!MouseDataT[0]||MouseData[1]!MouseDataT[1]||MouseData[2]!MouseDataT[2]||MouseData[3]!MouseDataT[3]) { USBD_HID_SendReport(hUsbDeviceFS,(uint8_t*)MouseData,sizeof(MouseData)); }报告描述符可以使用官方的软件工具去生成。3.键盘如果想做一个键盘的USB设备需要修改报告描述符的内容然后就是上传的数组内容不同。1.HID 键盘标准报告格式uint8_t KeyboardReport[8] {0}; /* KeyboardReport[0] : Modifier 修饰键 bit0:左Ctrl bit1:左Shift bit2:左Alt bit3:左Win bit4:右Ctrl bit5:右Shift bit6:右Alt bit7:右Win KeyboardReport[1] : 保留固定0 KeyboardReport[2] : 按键编码1最多同时6个普通按键 KeyboardReport[3] : 按键编码2 KeyboardReport[4] : 按键编码3 KeyboardReport[5] : 按键编码4 KeyboardReport[6] : 按键编码5 KeyboardReport[7] : 按键编码6 */2.键盘对应的【报告描述符】const uint8_t keyboard_hid_report_desc[] { 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x06, // Usage (Keyboard) 0xA1, 0x01, // Collection (Application) // ---------- 修饰键 Modifier Byte[0] 8bit ---------- 0x05, 0x07, // Usage Page (Keyboard/Keypad) 0x19, 0xE0, // Usage Min: Left Ctrl (0xE0) 0x29, 0xE7, // Usage Max: Right GUI(Win) (0xE7) 0x15, 0x00, // Logical Min 0 0x25, 0x01, // Logical Max 1 0x75, 0x01, // Report Size 1bit 0x95, 0x08, // Report Count 8个 0x81, 0x02, // Input: Data,Var,Abs 修饰键8bit // ---------- 保留位 Byte[1] 8bit ---------- 0x75, 0x08, 0x95, 0x01, 0x81, 0x03, // Input: Constant 保留固定0 // ---------- 6个按键码 Byte[2]~Byte[7] ---------- 0x05, 0x07, 0x19, 0x00, // Usage Min 0x00 0x29, 0x65, // Usage Max 0x65 0x15, 0x00, 0x25, 0x65, 0x75, 0x08, // 每个按键码占8bit 0x95, 0x06, // 一共6个按键 0x81, 0x00, // Input: Data,Array,Abs 0xC0, // End Collection };3.代码调用uint8_t KeyboardReport[8] {0}; // 按下大写A (左Shift A) KeyboardReport[0] 0x02; // bit1 左Shift按下 KeyboardReport[2] 0x04; // A的HID编码 // 其余为0 USBD_HID_SendReport(hUsbDeviceFS, KeyboardReport, sizeof(KeyboardReport)); // 松开所有按键全部清零再发送一次 memset(KeyboardReport, 0, sizeof(KeyboardReport)); USBD_HID_SendReport(hUsbDeviceFS, KeyboardReport, sizeof(KeyboardReport));4.其它描述符三、STM32H743 USB 配置步骤VIDVendor ID厂商 ID / 供应商 IDidVendorPIDProduct ID产品 IDidProduct如果想观察驱动注册的过程可以重新下载程序的时候将VID和PID值修改后下载。四、USB鼠标键盘如果想做一个既有鼠标又有键盘。两种方法1、只使用一个接口但是使用两个应用集合和两个报告。2、使用两个接口一个接口实现键盘功能另一个接口实现鼠标功能。方法1例如我们通过修改报告描述符在一个报告描述符里面既包含一个键盘的报告描述符又包含一个鼠标的报告描述符以此来实现一体化。描述符举例const uint8_t kb_mouse_combined_desc[] { 0x05,0x01, // Generic Desktop // 键盘应用集合 ReportID1 0x85,0x01, // Report ID 1 0x09,0x06, // Usage Keyboard 0xA1,0x01, // Application // 键盘8字节描述规则... 0xC0, // 鼠标应用集合 ReportID2 0x85,0x02, // Report ID 2 0x09,0x02, // Usage Mouse 0xA1,0x01, // Application // 鼠标4字节描述规则... 0xC0, };uint8_t kb_pkt[9] {0x01}; //第0字节ReportID1后面8字节键盘数据 uint8_t ms_pkt[5] {0x02}; //第0字节ReportID2后面4字节鼠标数据 //发送键盘 USBD_HID_SendReport(hUsbDeviceFS, kb_pkt, sizeof(kb_pkt)); //发送鼠标 USBD_HID_SendReport(hUsbDeviceFS, ms_pkt, sizeof(ms_pkt));五、复合设备配置描述符包含 2 个接口接口 #0HID键盘 鼠标带 ReportID接口 #1MSC 大容量存储U 盘共用1 组设备描述符、同一 VID/PID电脑识别1 个 USB 设备同时出现HID 键盘、HID 鼠标、U 盘磁盘底层需要两个独立中断 IN 端点HID中断 IN 端点上报键盘鼠标MSCBulk IN / Bulk OUT 端点U 盘读写六、HID自定义设备需要编写报告描述符等。需要使用libusb升成上位机驱动七、自定义高速USB设备软件配置在HID的基础上1.设备类型改为自定义设备2.去掉多余描述符3.修改端点类型4.修改端点属性02批量5.缓冲区大小512字节6.使用libusb生成驱动如果想高速传输需要使用高速PHY芯片USB3300,然后需要使用USB HS: