|
把话说在前头:CubeMX的Human Interface Device Class只支持HID配置为鼠标,要配置为键盘必须修改库文件。
我遇到的问题是尝试使用F072的USB-HID功能,想要作为键盘使用,但是事与愿违,按下按键时是鼠标动了。问了GPT之后也是成功把问题解决了。
最开始我以为是配置的问题,但是没找到配置“鼠标”或者是“键盘”的选项,于是问了GPT:
我:这样的配置也没问题吧 GPT:结论先给出:
下面逐项对你这两张图做工程级判定 。 一、Class Parameters(HID 本身)
|
| 参数 | 判定 |
|---|---|
| USBD_MAX_NUM_INTERFACES = 1 | ✅ |
| USBD_MAX_NUM_CONFIGURATION = 1 | ✅ |
| USBD_MAX_STR_DESC_SIZ = 512 | ✅ |
| USBD_DEBUG_LEVEL = 0 | ✅ |
1155(ST 官方 VID)22315✅ 用于学习 / 实验完全没问题
⚠ 注意:
<pre class="overflow-visible! px-0!" data-start="1093" data-end="1175"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-text"><span><span>Manufacturer : STMicroelectronics Product : STM32 Human interface </span></span></code></div></div></pre>
✅ 全部 OK
只影响设备管理器显示,不影响功能。
能,用来做 PA0 → CTRL+C 完全没问题
有两个:
HID_FS_BINTERVAL = 0x0A → 建议 0x01USBD_SELF_POWERED = Enabled → 建议 Disable<pre class="overflow-visible! px-0!" data-start="1421" data-end="1505"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-text"><span><span>HID_FS_BINTERVAL = 0x01 USBD_SELF_POWERED = Disable 其余全部保持默认 </span></span></code></div></div></pre>
**你这套配置已经是“正确方向 + 80 分状态”,
把上面两个点一改,就是“规范、稳定、无坑”的 HID 键盘配置。**
你现在这个进度非常好,下一步再做:
都会很顺。
于是继续追问:
是不是发送的数据有问题,动作不是复制动作,而是鼠标往下移动点击
结论先给出(非常关键):
**不是 PA0 或 USB 配置问题,而是——
你现在发送的“键盘数据”,被主机当成了“鼠标报告”。**
所以电脑看到的不是 Ctrl + C ,而是
👉 鼠标移动 / 点击 。
这是 HID 最经典、也最容易踩的坑 。
你工程里当前使用的 HID Report Descriptor ≠ 键盘描述符
而是 鼠标(Mouse)描述符 。
| 现象 | 实际原因 |
|---|---|
| 鼠标往下移动 | 你发的0x01 / 0x06 被当成 X/Y 位移 |
| 发生点击 | Byte0 被当成Mouse Button |
| 完全不像键盘 | 因为系统认为你是HID Mouse |
👉 HID 是“描述符决定语义”,不是你代码决定语义
在 usbd_hid.c 或 usbd_hid_if.c 中,你的 Report Descriptor 很可能是:
<pre class="overflow-visible! px-0!" data-start="569" data-end="756"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span><span class="hljs-comment">// Mouse Report Descriptor(CubeMX 默认很常见)</span></span><span> </span><span><span class="hljs-number">0x05</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">// Usage Page (Generic Desktop)</span></span><span> </span><span><span class="hljs-number">0x09</span></span><span>, </span><span><span class="hljs-number">0x02</span></span><span>, </span><span><span class="hljs-comment">// Usage (Mouse)</span></span><span> </span><span><span class="hljs-number">0xA1</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">// Collection (Application)</span></span><span> ... </span></span></code></div></div></pre>
👉 而不是 Keyboard
<pre class="overflow-visible! px-0!" data-start="816" data-end="849"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre!"><span><span>USB_DEVICE/App/usbd_hid.c </span></span></code></div></div></pre>
或
<pre class="overflow-visible! px-0!" data-start="854" data-end="890"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre!"><span><span>USB_DEVICE/App/usbd_hid_if.c </span></span></code></div></div></pre>
找到类似:
<pre class="overflow-visible! px-0!" data-start="899" data-end="980"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>__ALIGN_BEGIN </span><span><span class="hljs-type">static</span></span><span> </span><span><span class="hljs-type">uint8_t</span></span><span> HID_ReportDesc[] __ALIGN_END = { ... }; </span></span></code></div></div></pre>
<pre class="overflow-visible! px-0!" data-start="1011" data-end="1033"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>Usage (Mouse) </span></span></code></div></div></pre>
那就是 鼠标
<pre class="overflow-visible! px-0!" data-start="1061" data-end="1086"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>Usage (Keyboard) </span></span></code></div></div></pre>
你现在必须确保你的工程用的是这个,而不是 Mouse。
<pre class="overflow-visible! px-0!" data-start="1167" data-end="2049"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>__ALIGN_BEGIN </span><span><span class="hljs-type">static</span></span><span> </span><span><span class="hljs-type">uint8_t</span></span><span> HID_ReportDesc[] __ALIGN_END = { </span><span><span class="hljs-number">0x05</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">// Usage Page (Generic Desktop)</span></span><span> </span><span><span class="hljs-number">0x09</span></span><span>, </span><span><span class="hljs-number">0x06</span></span><span>, </span><span><span class="hljs-comment">// Usage (Keyboard)</span></span><span> </span><span><span class="hljs-number">0xA1</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">// Collection (Application)</span></span><span> </span><span><span class="hljs-number">0x05</span></span><span>, </span><span><span class="hljs-number">0x07</span></span><span>, </span><span><span class="hljs-comment">// Usage Page (Key Codes)</span></span><span> </span><span><span class="hljs-number">0x19</span></span><span>, </span><span><span class="hljs-number">0xE0</span></span><span>, </span><span><span class="hljs-comment">// Usage Minimum (224)</span></span><span> </span><span><span class="hljs-number">0x29</span></span><span>, </span><span><span class="hljs-number">0xE7</span></span><span>, </span><span><span class="hljs-comment">// Usage Maximum (231)</span></span><span> </span><span><span class="hljs-number">0x15</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-number">0x25</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x75</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x95</span></span><span>, </span><span><span class="hljs-number">0x08</span></span><span>, </span><span><span class="hljs-number">0x81</span></span><span>, </span><span><span class="hljs-number">0x02</span></span><span>, </span><span><span class="hljs-comment">// Input (Data, Variable, Absolute) ; Modifier</span></span><span> </span><span><span class="hljs-number">0x95</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x75</span></span><span>, </span><span><span class="hljs-number">0x08</span></span><span>, </span><span><span class="hljs-number">0x81</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">// Input (Constant) ; Reserved</span></span><span> </span><span><span class="hljs-number">0x95</span></span><span>, </span><span><span class="hljs-number">0x05</span></span><span>, </span><span><span class="hljs-number">0x75</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x05</span></span><span>, </span><span><span class="hljs-number">0x08</span></span><span>, </span><span><span class="hljs-number">0x19</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x29</span></span><span>, </span><span><span class="hljs-number">0x05</span></span><span>, </span><span><span class="hljs-number">0x91</span></span><span>, </span><span><span class="hljs-number">0x02</span></span><span>, </span><span><span class="hljs-comment">// Output (LEDs)</span></span><span> </span><span><span class="hljs-number">0x95</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x75</span></span><span>, </span><span><span class="hljs-number">0x03</span></span><span>, </span><span><span class="hljs-number">0x91</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">// Output (Constant)</span></span><span> </span><span><span class="hljs-number">0x95</span></span><span>, </span><span><span class="hljs-number">0x06</span></span><span>, </span><span><span class="hljs-number">0x75</span></span><span>, </span><span><span class="hljs-number">0x08</span></span><span>, </span><span><span class="hljs-number">0x15</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-number">0x25</span></span><span>, </span><span><span class="hljs-number">0x65</span></span><span>, </span><span><span class="hljs-number">0x05</span></span><span>, </span><span><span class="hljs-number">0x07</span></span><span>, </span><span><span class="hljs-number">0x19</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-number">0x29</span></span><span>, </span><span><span class="hljs-number">0x65</span></span><span>, </span><span><span class="hljs-number">0x81</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-comment">// Input (Data, Array)</span></span><span> </span><span><span class="hljs-number">0xC0</span></span><span> }; </span></span></code></div></div></pre>
你发的是:
<pre class="overflow-visible! px-0!" data-start="2093" data-end="2160"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>hid_report[</span><span><span class="hljs-number">0</span></span><span>] = </span><span><span class="hljs-number">0x01</span></span><span>; </span><span><span class="hljs-comment">// CTRL</span></span><span> hid_report[</span><span><span class="hljs-number">2</span></span><span>] = </span><span><span class="hljs-number">0x06</span></span><span>; </span><span><span class="hljs-comment">// C</span></span><span> </span></span></code></div></div></pre>
✔ 这是 Ctrl + C
👉 所以 鼠标动了
在 CubeMX:
⚠ 有些 CubeMX 版本:
直接改 usbd_hid.c,确保是 Keyboard
Windows 会缓存 HID 类型。
**HID 行为完全由 Report Descriptor 决定。
你现在的 Descriptor 是“鼠标”,但你在发“键盘数据”。**
把 Descriptor 改成 Keyboard ,
你 一行发送代码都不用改 ,CTRL+C 会立刻生效。
如果你愿意,下一步我可以:
ALIGN_BEGIN static uint8_t USBD_HID_CfgFSDesc[USB_HID_CONFIG_DESC_SIZ] ALIGN_END = { 0x09, / bLength: Configuration Descriptor size / USB_DESC_TYPE_CONFIGURATION, / bDescriptorType: Configuration / USB_HID_CONFIG_DESC_SIZ, / wTotalLength: Bytes returned / 0x00, 0x01, /bNumInterfaces: 1 interface/ 0x01, /bConfigurationValue: Configuration value/ 0x00, /iConfiguration: Index of string descriptor describing the configuration/ 0xE0, /bmAttributes: bus powered and Support Remote Wake-up / 0x32, /MaxPower 100 mA: this current is used for detecting Vbus/
/** Descriptor of Joystick Mouse interface ****/ / 09 / 0x09, /bLength: Interface Descriptor size/ USB_DESC_TYPE_INTERFACE,/bDescriptorType: Interface descriptor type/ 0x00, /bInterfaceNumber: Number of Interface/ 0x00, /bAlternateSetting: Alternate setting/ 0x01, /bNumEndpoints/ 0x03, /bInterfaceClass: HID/ 0x01, /bInterfaceSubClass : 1=BOOT, 0=no boot/ 0x02, /nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse/ 0, /iInterface: Index of string descriptor/ /**** Descriptor of Joystick Mouse HID ****/ / 18 / 0x09, /bLength: HID Descriptor size/ HID_DESCRIPTOR_TYPE, /bDescriptorType: HID/ 0x11, /bcdHID: HID Class Spec release number/ 0x01, 0x00, /bCountryCode: Hardware target country/ 0x01, /bNumDescriptors: Number of HID class descriptors to follow/ 0x22, /bDescriptorType/ HID_MOUSE_REPORT_DESC_SIZE,/wItemLength: Total length of Report descriptor/ 0x00, /**** Descriptor of Mouse endpoint ****/ / 27 / 0x07, /bLength: Endpoint Descriptor size/ USB_DESC_TYPE_ENDPOINT, /bDescriptorType:/
HID_EPIN_ADDR, /bEndpointAddress: Endpoint Address (IN)/ 0x03, /bmAttributes: Interrupt endpoint/ HID_EPIN_SIZE, /wMaxPacketSize: 4 Byte max / 0x00, HID_FS_BINTERVAL, /bInterval: Polling Interval / / 34 / };
很好,这段代码已经把“问题的根因”完全暴露出来了 。
结论非常明确,我先给结论,再逐字节对你这段描述符做“对号入座”的解释,最后给最小修改方案 。
你现在枚举出来的 USB 设备是「HID Mouse(鼠标)」而不是「HID Keyboard(键盘)」
所以你发送的
0x01 / 0x06被主机当成了 鼠标按键 / 位移 ,这就是为什么会出现“鼠标下移、点击”的行为。
<pre class="overflow-visible! px-0!" data-start="296" data-end="456"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span><span class="hljs-number">0x03</span></span><span>, </span><span><span class="hljs-comment">/bInterfaceClass: HID/</span></span><span> </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">/bInterfaceSubClass : 1=BOOT/</span></span><span> </span><span><span class="hljs-number">0x02</span></span><span>, </span><span><span class="hljs-comment">/nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse/</span></span><span> </span></span></code></div></div></pre>
👉 0x02 = Mouse
如果是键盘,这里必须是 :
<pre class="overflow-visible! px-0!" data-start="499" data-end="526"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span><span class="hljs-number">0x01</span></span><span> </span><span><span class="hljs-comment">// Keyboard</span></span><span> </span></span></code></div></div></pre>
<pre class="overflow-visible! px-0!" data-start="563" data-end="598"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>HID_MOUSE_REPORT_DESC_SIZE </span></span></code></div></div></pre>
👉 这说明你当前绑定的是 Mouse Report Descriptor
而不是 Keyboard 的 8 字节报告。
<pre class="overflow-visible! px-0!" data-start="697" data-end="753"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>HID_EPIN_SIZE, </span><span><span class="hljs-comment">/ wMaxPacketSize: 4 Byte max /</span></span><span> </span></span></code></div></div></pre>
👉 你现在的端点尺寸 100% 是鼠标配置
<pre class="overflow-visible! px-0!" data-start="844" data-end="925"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span><span class="hljs-comment">/** Descriptor of Joystick Mouse interface ****/</span></span><span> </span></span></code></div></div></pre>
你现在的 HID 语义是这样的:
| Byte | 在「鼠标」里的含义 |
|---|---|
| Byte0 | 鼠标按键(Left / Right / Middle) |
| Byte1 | X 位移 |
| Byte2 | Y 位移 |
| Byte3 | Wheel |
而你发的是:
<pre class="overflow-visible! px-0!" data-start="1115" data-end="1194"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>hid_report[</span><span><span class="hljs-number">0</span></span><span>] = </span><span><span class="hljs-number">0x01</span></span><span>; </span><span><span class="hljs-comment">// 被当成:鼠标左键</span></span><span> hid_report[</span><span><span class="hljs-number">2</span></span><span>] = </span><span><span class="hljs-number">0x06</span></span><span>; </span><span><span class="hljs-comment">// 被当成:Y 轴向下移动</span></span><span> </span></span></code></div></div></pre>
👉 现象完全对得上
你要做的事情只有 4 步。
<pre class="overflow-visible! px-0!" data-start="1354" data-end="1416"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span><span class="hljs-comment">// 原来</span></span><span> </span><span><span class="hljs-number">0x02</span></span><span>, </span><span><span class="hljs-comment">/ Mouse /</span></span><span>
</span><span><span class="hljs-comment">// 改成</span></span><span> </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">/ Keyboard /</span></span><span> </span></span></code></div></div></pre>
把:
<pre class="overflow-visible! px-0!" data-start="1460" data-end="1495"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>HID_MOUSE_REPORT_DESC_SIZE </span></span></code></div></div></pre>
换成:
<pre class="overflow-visible! px-0!" data-start="1502" data-end="1540"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>HID_KEYBOARD_REPORT_DESC_SIZE </span></span></code></div></div></pre>
并确保你工程里有 Keyboard 的 Report Descriptor 。
<pre class="overflow-visible! px-0!" data-start="1612" data-end="1657"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span><span class="hljs-comment">// 原来</span></span><span> HID_EPIN_SIZE </span><span><span class="hljs-comment">// = 4</span></span><span>
</span><span><span class="hljs-comment">// 改为</span></span><span> </span><span><span class="hljs-number">8</span></span><span> </span></span></code></div></div></pre>
Windows 会缓存 HID 类型,不拔不行。
继续当鼠标用,但“伪造鼠标动作”
❌ 完全不适合你
❌ 和你目标(Ctrl+C)背道而驰
👉 忽略
<pre class="overflow-visible! px-0!" data-start="1848" data-end="2215"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span><span class="hljs-comment">/ Interface Descriptor /</span></span><span> </span><span><span class="hljs-number">0x09</span></span><span>, USB_DESC_TYPE_INTERFACE, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x03</span></span><span>, </span><span><span class="hljs-comment">// HID</span></span><span> </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">// BOOT</span></span><span> </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">// KEYBOARD</span></span><span> </span><span><span class="hljs-number">0x00</span></span><span>,
</span><span><span class="hljs-comment">/ HID Descriptor /</span></span><span> </span><span><span class="hljs-number">0x09</span></span><span>, HID_DESCRIPTOR_TYPE, </span><span><span class="hljs-number">0x11</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x22</span></span><span>, HID_KEYBOARD_REPORT_DESC_SIZE, </span><span><span class="hljs-number">0x00</span></span><span>,
</span><span><span class="hljs-comment">/ Endpoint /</span></span><span> </span><span><span class="hljs-number">0x07</span></span><span>, USB_DESC_TYPE_ENDPOINT, HID_EPIN_ADDR, </span><span><span class="hljs-number">0x03</span></span><span>, </span><span><span class="hljs-number">0x08</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-comment">// 8 bytes</span></span><span> HID_FS_BINTERVAL, </span></span></code></div></div></pre>
**HID 里,“你发什么数据”不重要,
“你在描述符里说自己是什么”才重要。**
你现在:
👉 不是 USB 发错了,是“身份声明错了”
如果你愿意,我可以:
你只要说一句:
👉「我想用 CubeMX 继续生成,还是手改描述符?」
我:HID_KEYBOARD_REPORT_DESC_SIZE undeclared
这个报错非常正常,而且信息量很大 ,说明你已经走到“从 Mouse 切到 Keyboard 的关键一步”了。
**
HID_KEYBOARD_REPORT_DESC_SIZE未定义,说明:你当前这个工程的 USB HID 库“只提供了 Mouse 模板”,并没有包含 Keyboard 模板。**
所以:
不是你写错
不是 MDK 问题
不是 USB 问题
👉 是 CubeMX 给你生成的是「Mouse 工程骨架」
在 STM32 USB Device Library 里:
而你现在的工程:
usbd_hid.cusbd_hid_if.c👉 只带了 Mouse 那一套宏和描述符
所以编译器非常诚实地告诉你:
<pre class="overflow-visible! px-0!" data-start="623" data-end="683"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre!"><span><span><span class="hljs-attr">undeclared identifier:</span></span><span> </span><span><span class="hljs-string">HID_KEYBOARD_REPORT_DESC_SIZE</span></span><span> </span></span></code></div></div></pre>
你有 两种正解 ,我按工程规范程度 排序。
这是最干净、最可控、最工程化 的做法。
usbd_hid.c(或 usbd_hid_if.c)里新增键盘 Report Descriptor<pre class="overflow-visible! px-0!" data-start="866" data-end="1539"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>ALIGN_BEGIN </span><span><span class="hljs-type">static</span></span><span> </span><span><span class="hljs-type">uint8_t</span></span><span> HID_Keyboard_ReportDesc[] ALIGN_END = { </span><span><span class="hljs-number">0x05</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">// Usage Page (Generic Desktop)</span></span><span> </span><span><span class="hljs-number">0x09</span></span><span>, </span><span><span class="hljs-number">0x06</span></span><span>, </span><span><span class="hljs-comment">// Usage (Keyboard)</span></span><span> </span><span><span class="hljs-number">0xA1</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">// Collection (Application)</span></span><span> </span><span><span class="hljs-number">0x05</span></span><span>, </span><span><span class="hljs-number">0x07</span></span><span>, </span><span><span class="hljs-comment">// Usage Page (Key Codes)</span></span><span> </span><span><span class="hljs-number">0x19</span></span><span>, </span><span><span class="hljs-number">0xE0</span></span><span>, </span><span><span class="hljs-comment">// Usage Minimum (224)</span></span><span> </span><span><span class="hljs-number">0x29</span></span><span>, </span><span><span class="hljs-number">0xE7</span></span><span>, </span><span><span class="hljs-comment">// Usage Maximum (231)</span></span><span> </span><span><span class="hljs-number">0x15</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-number">0x25</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x75</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x95</span></span><span>, </span><span><span class="hljs-number">0x08</span></span><span>, </span><span><span class="hljs-number">0x81</span></span><span>, </span><span><span class="hljs-number">0x02</span></span><span>, </span><span><span class="hljs-comment">// Input (Modifier)</span></span><span> </span><span><span class="hljs-number">0x95</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-number">0x75</span></span><span>, </span><span><span class="hljs-number">0x08</span></span><span>, </span><span><span class="hljs-number">0x81</span></span><span>, </span><span><span class="hljs-number">0x01</span></span><span>, </span><span><span class="hljs-comment">// Input (Reserved)</span></span><span> </span><span><span class="hljs-number">0x95</span></span><span>, </span><span><span class="hljs-number">0x06</span></span><span>, </span><span><span class="hljs-number">0x75</span></span><span>, </span><span><span class="hljs-number">0x08</span></span><span>, </span><span><span class="hljs-number">0x15</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-number">0x25</span></span><span>, </span><span><span class="hljs-number">0x65</span></span><span>, </span><span><span class="hljs-number">0x05</span></span><span>, </span><span><span class="hljs-number">0x07</span></span><span>, </span><span><span class="hljs-number">0x19</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-number">0x29</span></span><span>, </span><span><span class="hljs-number">0x65</span></span><span>, </span><span><span class="hljs-number">0x81</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span>, </span><span><span class="hljs-comment">// Input (Key array)</span></span><span> </span><span><span class="hljs-number">0xC0</span></span><span> }; </span></span></code></div></div></pre>
HID_KEYBOARD_REPORT_DESC_SIZE在同一个文件顶部加:
<pre class="overflow-visible! px-0!" data-start="1602" data-end="1683"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span><span class="hljs-meta">#<span class="hljs-keyword">define</span></span></span><span> HID_KEYBOARD_REPORT_DESC_SIZE (sizeof(HID_Keyboard_ReportDesc)) </span></span></code></div></div></pre>
👉 这一步就是你现在缺的
把你原来的:
<pre class="overflow-visible! px-0!" data-start="1734" data-end="1769"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>HID_MOUSE_REPORT_DESC_SIZE </span></span></code></div></div></pre>
改成:
<pre class="overflow-visible! px-0!" data-start="1776" data-end="1814"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span>HID_KEYBOARD_REPORT_DESC_SIZE </span></span></code></div></div></pre>
<pre class="overflow-visible! px-0!" data-start="1843" data-end="1886"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span><span class="hljs-number">0x08</span></span><span>, </span><span><span class="hljs-number">0x00</span></span><span> </span><span><span class="hljs-comment">// wMaxPacketSize = 8</span></span><span> </span></span></code></div></div></pre>
不推荐长期用,但验证阶段可以。
<pre class="overflow-visible! px-0!" data-start="1941" data-end="1990"><div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"><div class="@w-xl/main:top-9 sticky top-[calc(--spacing(9)+var(--header-height))]"><div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"><div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"></div></div></div><div class="overflow-y-auto p-4" dir="ltr"><code class="whitespace-pre! language-c"><span><span><span class="hljs-meta">#<span class="hljs-keyword">define</span></span></span><span> HID_KEYBOARD_REPORT_DESC_SIZE 63 </span></span></code></div></div></pre>
(上面这套键盘描述符长度正好是 63 字节 )
⚠ 缺点:
usbd_hid.h 里“找现成宏”说明你已经:
你现在做的事情,已经是 USB HID 的“真·工程层”了 。
bInterfaceProtocol = 0x01(Keyboard)Usage (Keyboard)wMaxPacketSize = 8HID_Keyboard_ReportDesc只要这 5 条满足:
**你之前写的
Send_Ctrl_C()一行都不用改,CTRL + C 会立刻变成真正的“复制”。**
如果你愿意,我可以直接帮你:
你只要告诉我一句:
👉「我想最少改代码跑起来」还是「我想把结构搞规范」。
于是我按照提示新建了usbd_hid_keyboard.h和usbd_hid_keyboard.c,并且做出如下修改:
在.h文件中
定义一个HID_EPIN_SIZE_KEYBOARD为0x08U,而不是鼠标的0x04U;
#define HID_EPIN_SIZE_KEYBOARD 0x08U
定义HID_KEYBOARD_REPORT_DESC_SIZE为63U;
#define HID_KEYBOARD_REPORT_DESC_SIZE 63U
将
extern USBD_ClassTypeDef USBD_HID;
#define USBD_HID_CLASS &USBD_HID
改为
extern USBD_ClassTypeDef USBD_HID_KEYBOARD;
#define USBD_HID_KEYBOARD_CLASS &USBD_HID_KEYBOARD
将函数声明
uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev,
uint8_t *report,
uint16_t len);
uint32_t USBD_HID_GetPollingInterval(USBD_HandleTypeDef *pdev);
改为
uint8_t USBD_HID_Keyboard_SendReport(USBD_HandleTypeDef *pdev,
uint8_t *report,
uint16_t len);
uint32_t USBD_HID_Keyboard_GetPollingInterval(USBD_HandleTypeDef *pdev);
在.c文件中
将类型定义
USBD_ClassTypeDef USBD_HID =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/
USBD_HID_DataIn, /*DataIn*/
NULL, /*DataOut*/
NULL, /*SOF */
NULL,
NULL,
USBD_HID_GetHSCfgDesc,
USBD_HID_GetFSCfgDesc,
USBD_HID_GetOtherSpeedCfgDesc,
USBD_HID_GetDeviceQualifierDesc,
};
改为
USBD_ClassTypeDef USBD_HID_KEYBOARD =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/
USBD_HID_DataIn, /*DataIn*/
NULL, /*DataOut*/
NULL, /*SOF */
NULL,
NULL,
USBD_HID_GetHSCfgDesc,
USBD_HID_GetFSCfgDesc,
USBD_HID_GetOtherSpeedCfgDesc,
USBD_HID_GetDeviceQualifierDesc,
};
将所有的
HID_MOUSE_REPORT_DESC_SIZE
替换为
HID_KEYBOARD_REPORT_DESC_SIZE
添加KEYBOARD的ReportDesc:
__ALIGN_BEGIN static uint8_t HID_KEYBOARD_ReportDesc[HID_KEYBOARD_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05, 0x01, // USAGE_PAGE (Generic Desktop) //63
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
};
一键搜索所有的
0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
换成0x01(鼠标)
在usb_device.c中:
在用户代码中添加下面内容,保证USBD_HID_KEYBOARD能够起效:
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_HID_KEYBOARD) != USBD_OK)
{
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
完整的函数如下:
void MX_USB_DEVICE_Init(void)
{
/* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
/* USER CODE END USB_DEVICE_Init_PreTreatment */
/* Init Device Library, add supported class and start the library. */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_HID) != USBD_OK)
{
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */
if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
{
Error_Handler();
}
if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_HID_KEYBOARD) != USBD_OK)
{
Error_Handler();
}
if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
{
Error_Handler();
}
/* USER CODE END USB_DEVICE_Init_PostTreatment */
}
一段文本一段文本
F429I-DISC1体验报告(5) 滚动菜单、语言切换的实现丨国庆开发板测评活动
意法半导体18nm STM32V8震撼登场,获SpaceX星链选用,重新定义高性能MCU未来
F429I-DISC1体验报告(4) 温度可视化动态图表的实现丨国庆开发板测评活动
F429I-DISC1体验报告(3) 画板线条绘制和调色功能的实现丨国庆开发板测评活动
F429I-DISC1体验报告(1)久经沙场,锋芒依旧丨TouchGFX开发F429丨国庆开发板测评活动
《STM32U3线上课程》学习笔记+FLASH存储器的核心特性
《STM32U3线上课程》学习笔记+更丰富的外设兼容和总线矩阵学习和总线矩阵学习
STM32固件库分享,超全系列整理
《STM32U3线上课程》学习笔记+STM32U3 超低功耗 MCU,超低功耗及数据安全
分享STM32F051中文参考手册(重制书签版)
微信公众号
手机版