
MicroPython pyboard 化身 USB 鼠标从 boot.py 配置到加速度计控制实战【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址: https://gitcode.com/gh_mirrors/mi/micropython本教程基于仓库中的 docs/pyboard/tutorial/usb_mouse.rst 展开讲解如何把 pyboard 从默认的 U 盘模式切换为 USB 鼠标HID 设备模式先通过boot.py中的pyb.usb_mode(VCPHID)完成模式切换再借助pyb.USB_HID().send()手动发送鼠标事件最后用板载加速度计实现倾斜即移动的体感鼠标。读完本文你将掌握 pyboard USB 设备接口的配置原理、HID 报告的数据格式以及安全模式safe mode这一在 HID 模式下救急编辑文件的关键技巧并能举一反三地自定义 HID 键盘等设备。pyboard 的 USB 设备本质接口interface而非单一实体pyboard 本身就是一个 USB 设备默认配置为虚拟串口 大容量存储U 盘。在 ports/stm32/usb.c 的源码注释中作者明确阐述了其设计哲学MicroPython bindings for USB:pyb.usb_mode(...)configures the USB on the board. The USB itself is not an entity, rather the interfaces are, and can be accessed by creating objects, such aspyb.USB_VCP()andpyb.USB_HID().也就是说USB 本身不是一个对象而是多个**接口interface**的组合每个接口可以通过独立的 Python 对象访问pyb.USB_VCP()—— 虚拟串口接口用于读写数据、承载 REPLpyb.USB_HID()—— 人机交互设备接口用于发送/接收 HID 报告本例中即鼠标事件MSC 接口 —— 大容量存储即你看到的 U 盘。这套接口组合在 ports/stm32/modpyb.c 中注册到pyb模块pyb.usb_mode、pyb.USB_HID、pyb.USB_VCP、pyb.hid_mouse、pyb.hid_keyboard其中后两者仅在MICROPY_HW_USB_HID使能时编译旧版遗留的全局发送函数已标记为 deprecated推荐使用USB_HID.send。第一步编辑 boot.py开启 VCPHID 模式boot.py是 pyboard 上电后最先执行的脚本负责配置 USB 和文件系统应用代码放在main.py。全新的boot.py大致如下# boot.py -- run on boot to configure USB and filesystem # Put app code in main.py import pyb #pyb.main(main.py) # main script to run after this one #pyb.usb_mode(VCPMSC) # act as a serial and a storage device #pyb.usb_mode(VCPHID) # act as a serial device and a mouse启用鼠标模式只需取消最后一行注释pyb.usb_mode(VCPHID) # act as a serial device and a mouse如果你已经改过boot.py最小的可用写法只有两行import pyb pyb.usb_mode(VCPHID)这行代码告诉 pyboard 在上电时把自己配置为同时具备 VCPVirtual COM Port虚拟串口和 HIDHuman Interface Device本例为鼠标两种 USB 接口的设备。注意此时板子同时还是 VCP 虚拟串口因此你依然可以用串口程序连接 REPL 交互这也是后续手动发送鼠标事件的前提。保存文件后弹出/卸载 pyboard 的 U 盘再按 RST 复位键。此时电脑应能识别出一个新的鼠标设备——恭喜你的 pyboard 已经变成鼠标了。pyb.usb_mode 支持的全部模式在 ports/stm32/usb.c 中定义了完整的模式表pyb_usb_mode_tablepyb.usb_mode接受的第一个参数即表中字符串模式字符串含义默认 PID 宏VCP仅虚拟串口MICROPY_HW_USB_PID_CDCMSC仅大容量存储MICROPY_HW_USB_PID_MSCVCPMSC串口 U 盘默认MICROPY_HW_USB_PID_CDC_MSCVCPHID串口 HID鼠标/键盘MICROPY_HW_USB_PID_CDC_HIDVCPMSCHID串口 U 盘 HID 三合一MICROPY_HW_USB_PID_CDC_MSC_HID旧名称如CDC、CDCMSC、CDCHID出于向后兼容仍然支持对应源码中的deprecated_str字段。此外pyb.usb_mode()不带参数调用时返回当前模式字符串传入None则禁用 USB。部分板卡还支持双串口2xVCP等取决于MICROPY_HW_USB_CDC_NUM的编译配置。第二步手动发送鼠标事件理解 HID 报告格式用串口程序连接 REPL依次输入以下命令 hid pyb.USB_HID() hid.send((0, 100, 0, 0)) # (button status, x-direction, y-direction, scroll)鼠标应当向右移动 100 像素。send()接收的元组包含 4 个字节即一份标准的 4 字节鼠标 HID 报告button status按键状态bit0左键、bit1右键、bit2中键按下对应的位就置 1x-directionx 方向位移正数向右、负数向左有符号 8 位整数y-directiony 方向位移正数向下、负数向上注意坐标系与屏幕显示习惯相反scroll滚轮滚动量正负对应滚轮方向。100表示在 x 方向移动了 100 像素。报告是相对位移语义每次send发送的是一个增量多次发送即累积移动。让鼠标左右摆动 import math def osc(n, d): ... for i in range(n): ... hid.send((0, int(20 * math.sin(i / 10)), 0, 0)) ... pyb.delay(d) ... osc(100, 50)osc的第一个参数n是发送的鼠标事件次数第二个参数d是两次事件之间的延时毫秒。正弦函数把 x 位移变成平滑的正负交替鼠标便来回摆动。可以尝试修改幅度如 20、频率如i/10和延时如 50来感受参数对运动轨迹的影响。练习题利用math.cos和math.sin组合 x、y 分量让鼠标画出一个圆。USB_HID.send 的底层实现与边界pyb.USB_HID()在 ports/stm32/usb.c 中实现为pyb_usb_hid_send。其核心逻辑有两点值得注意两种入参形式既可以直接传bytes/bytearray也可以传元组或整数列表——元组/列表会被逐个转换成uint8_t字节这正是本教程hid.send((0, 100, 0, 0))可用的原因长度上限当入参是元组/列表时内部使用 8 字节临时缓冲byte temp_buf[8]超过 8 字节会抛出ValueError: tuple/list too large for HID report; use bytearray instead——自定义更大的报告如键盘 8 字节报告、多媒体按键报告时应改用bytearray传入返回值send成功后返回发送的字节数若底层USBD_HID_SendReport失败则返回0可用于检测链路状态。与send配套的还有USB_HID.recv(data, timeout5000)方法见 ports/stm32/usb.c用于接收主机发来的 HID 报告——在双向 HID 通信场景如模拟游戏手柄中会用到。第三步用加速度计做一个体感鼠标让鼠标跟随板子的倾斜角度移动核心代码如下可临时在 REPL 中逐行输入验证import pyb switch pyb.Switch() accel pyb.Accel() hid pyb.USB_HID() while not switch(): hid.send((0, accel.x(), accel.y(), 0)) pyb.delay(20)但问题来了板子当前是 HID 模式没有 U 盘你无法挂载文件系统去编辑main.py也无法改回boot.py……此时就需要进入**安全模式safe mode**来救场。进入安全模式的完整步骤安全模式的完整说明见 reset tutorial这里直接给出操作步骤按住USR 按键保持按住 USR按下并松开RST 按键此时 LED 会循环显示绿 → 橙 → 绿橙 → 回到绿……持续按住 USR直到只有橙色 LED 亮起然后松开 USR橙色 LED 会快速闪烁 4 次后熄灭现在你已处于安全模式。安全模式的源码级原理安全模式为什么能让你重新访问 U 盘从 ports/stm32/boardctrl.c 可以看到boot.py与main.py的执行都受复位模式reset_mode控制// boardctrl_run_boot_py bool run_boot_py state-reset_mode ! BOARDCTRL_RESET_MODE_SAFE_MODE; // boardctrl_run_main_py bool run_main_py state-reset_mode ! BOARDCTRL_RESET_MODE_SAFE_MODE pyexec_mode_kind PYEXEC_MODE_FRIENDLY_REPL;安全模式BOARDCTRL_RESET_MODE_SAFE_MODE见 ports/stm32/boardctrl.h下两者都不执行于是板子以默认 USB 配置启动——U 盘回来了你可以正常编辑boot.py和main.py。注意此时boot.py保持不变因为我们编辑完main.py后还要回到 HID 模式。复位模式的选择逻辑在 ports/stm32/boardctrl.c 的update_reset_mode中上电时检测 USR 开关是否按下若按下则 LED 以不同组合循环指示可选的复位模式通过 LED 组合编码选择。教程中的绿 → 橙 → 绿橙循环正是这一 LED 状态机在只有开关的 pyboard 上的呈现模式选定后 LED 会闪烁对应次数加以确认。提示安全模式下boot.py不执行USB 恢复正常默认配置因此 U 盘可见、串口可用方便你修改文件或调试。保存并运行把上述代码保存为main.pyboot.py保持pyb.usb_mode(VCPHID)不动弹出 U 盘并复位。板子现在就是一只倾斜控制的鼠标倾斜角度映射为 x/y 位移板子角度变化会带动鼠标移动按USR 按键即可停止鼠标运动while not switch()退出循环你会发现y 轴方向是反的——这是加速度计坐标轴方向决定的修复方法很简单在hid.send()的 y 分量前加负号hid.send((0, accel.x(), -accel.y(), 0))试试看能不能让鼠标纹丝不动地停在原地那说明你握板的手法极其稳定。第四步恢复正常模式如果放任不管pyboard 每次插入都会以鼠标模式运行。恢复正常模式的流程先进入安全模式步骤同上编辑boot.py把VCPHID那一行注释掉#pyb.usb_mode(VCPHID) # act as a serial device and a mouse保存文件弹出 U 盘复位板子。此时boot.py不再切换 USB 模式pyboard 恢复为默认的串口 U 盘形态。进阶鼠标协议之外——键盘模式与自定义报告描述符pyb.usb_mode在 ports/stm32/usb.c 中暴露了若干可选关键字参数其中hid参数决定了 HID 设备的协议描述默认值即pyb.hid_mousesubclass1即 boot 子类、protocol2即鼠标协议、轮询间隔 8ms、内置鼠标报告描述符见 ports/stm32/usb.c传pyb.hid_keyboard即可把 pyboard 变成 USB 键盘protocol1、8ms 轮询见 ports/stm32/usb.c也可以传自定义 5 元组(subclass, protocol, max_packet_len, polling_interval, report_desc)其中report_desc是一份完整的 HID 报告描述符bytes源码会将其复制保存以防被 GC 回收ports/stm32/usb.c。示例指定 VID/PID 的鼠标模式pyb.usb_mode(VCPHID, vid0xf055, pid0x9800) # 自定义厂商/产品 ID pyb.usb_mode(VCPHID, hidpyb.hid_keyboard) # 变成键盘除此之外pyb.usb_mode还支持port选择 USB 端口多 USB 的板卡可用、msc指定大容量存储逻辑单元如pyb.Flash()或 SD 卡等关键字参数。所有这些配置最终汇聚到 ports/stm32/usb.c 的pyb_usb_dev_init由 STM32 USB 设备栈usbd_cdc_msc_hid见 ports/stm32/usbdev/class/inc/usbd_cdc_msc_hid.h统一配置 VID/PID、选择接口组合并初始化各接口。总结本文完整走通了 pyboard 变身 USB 鼠标的四个阶段boot.py 配置模式 → REPL 手动验证 → 加速度计体感控制含安全模式自救→ 恢复正常模式。关键要点回顾pyb.usb_mode(VCPHID)是切换鼠标模式的唯一入口VCP 接口保留使 REPL 仍然可用USB_HID.send((btn, x, y, scroll))发送 4 字节相对位移报告元组会被自动转为字节超 8 字节需用bytearray加速度计方案的核心是while not switch(): hid.send((0, accel.x(), -accel.y(), 0))循环注意 y 轴取反HID 模式下无法挂载 U 盘通过按住 USR 复位进入安全模式即可重新编辑文件修改hid参数即可把同一套机制复用到 USB 键盘或自定义 HID 设备。如果想继续深入可以阅读 pyb.USB_HID 参考文档文中未列实际接口见 modpyb.c以及 pyb.usb_mode 相关文档并结合 ports/stm32/usbd_hid_interface.c 了解报告收发的中断级实现。【免费下载链接】micropythonMicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems项目地址: https://gitcode.com/gh_mirrors/mi/micropython创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考