基于STM32的USB设备开发实战——从HID到CDC虚拟串口
前言 在嵌入式开发的世界里,USB 可能是最矛盾的存在:一方面它无处不在,从键盘鼠标到U盘摄像头,几乎所有外设都在用;另一方面它又以复杂著称,四层协议栈、十几种传输类型、上百页的规格书,让很多工程师望而却步。 我第一次接触 USB 开发是在 2018 年。当时项目需要做一个自定义的 USB 数据采集设备,我拿着 STM32 的参考手册看了三天,愣是没搞懂端点(Endpoint)和管道(Pipe)到底有什么区别。网上的教程要么是「打开 CubeMX 点几下就行了」,要么是直接扔给你一整个库的代码,中间的关键步骤一概省略。 那一周我熬了三个通宵,把 USB 协议栈的源代码一行一行地啃完,才终于明白:USB 其实没那么难,难的是没有人把它讲清楚。 这篇文章就是为了解决这个问题。我会从最基础的 USB 协议概念讲起,一步步带你完成 HID 自定义设备和 CDC 虚拟串口的完整开发。不需要你有任何 USB 开发经验,只要你会用 STM32 和 HAL 库,跟着这篇文章走,就能做出自己的 USB 设备。 一、USB 协议基础:五分钟搞懂核心概念 在写代码之前,我们必须先搞懂 USB 的几个核心概念。这部分是整个 USB 开发的基石,理解了这些,后面的代码就只是按部就班而已。 1.1 主机与设备的主从关系 USB 是一个严格的主从架构: 主机(Host):只能是一个,通常是 PC 或手机,负责发起所有通信 设备(Device):可以有多个,只能被动响应主机的请求 这一点非常重要。USB 设备永远不能主动给主机发数据,它只能在主机询问的时候才能回复。这是很多新手踩的第一个坑——他们在设备端写了一个发送数据的循环,然后奇怪为什么主机收不到任何东西。 1.2 端点:USB 通信的基本单元 如果把 USB 比作一条公路,那么**端点(Endpoint)**就是这条公路上的车道。每个端点都有: 编号:0-15,其中端点 0 是控制端点,所有设备必须实现 方向:IN(设备→主机)或 OUT(主机→设备) 类型:控制传输、批量传输、中断传输、等时传输 最大包长:全速设备最大 64 字节,高速设备最大 1024 字节 举个例子:一个 USB 鼠标通常有两个端点:...