用 Teensy 4.1 做 DMA 输入设备
Teensy 4.1 完整搭建流程:焊接主机焊盘、用 Teensy Loader 刷写、接线顺序、串口或网络控制、回报率、描述符修改以及常见故障。
简短回答
先在主频 600 MHz 的 Teensy 4.1 主机焊盘上焊一个 5 针排针,再用 Teensy Loader 刷写透传固件。鼠标插主机端口,设备端口接游戏主机,然后由副机(第二台电脑)通过串口控制这块板子。
本页内容12
Teensy 4.1 是什么
Teensy 4.1 是 PJRC 出品的一块通用微控制器开发板,设计之初根本不是为这个用途准备的。这正是它便宜的原因,也是为什么只要你肯下功夫,它会成为这几种输入设备里能力最强的一个。
- 微控制器
- NXP i.MX RT1062,带硬件浮点单元的 ARM Cortex-M7
- 主频
- 默认 600 MHz,可在 IDE 中选择。用在这里不要超频
- 闪存
- 约 8 MB(7936 K),远超任何透传固件的需要
- 内存
- 共 1024 K,其中 512 K 是与处理器内核紧耦合的内存
- 设备端口
- 即 micro-USB 接口。USB 2.0 高速,480 Mbit/s。这一端朝向游戏主机
- 主机端口
- 板上的五个通孔焊盘,出厂时没有焊任何东西。根据所接设备,工作在 480、12 或 1.5 Mbit/s。你的鼠标插在这一端
- 主机端 5V
- 由芯片通过一个限流开关控制通断。在固件调用主机库的 begin 函数之前,焊盘上没有供电
- 硬件串口
- 八路 UART,适合想要一条不经过 USB 设备端口的串口链路时使用
- 以太网
- 支持 10/100,但 magjack 是需要另外焊接的独立套件。串口方案用不到它
- 固件写入
- 使用 Teensy Loader,装好 Teensyduino 后由 Arduino IDE 自动调用。板上有一个实体 Program 按钮,可以强制进入 bootloader
为什么选 Teensy,而不是现成的设备?
理由有三个,按照它们实际成为决定因素的频率排序。第一,固件由你自己编译,所以游戏主机看到哪个 USB 描述符、报告多久发一次,都由你决定,任何现成设备都做不到这一点。第二,主机控制器和设备控制器完全独立,透传不会和注入争抢带宽。第三,便宜。代价是你自己成了厂商:出了问题没有任何售后渠道,只有你自己的接线和你自己的代码。
警告
如何焊接 USB 主机端口
这是唯一必须做的焊接,也决定了后面的搭建能不能成功。主机焊盘是五个出厂未焊接的金属化通孔,分别是主机 5V、D- 和 D+ 差分对以及地线。顺序以丝印和官方引脚图卡为准,不要猜,也不要相信论坛帖子里的示意图。
- 找到板子上的五个主机焊盘,并对照 PJRC 官方的 Teensy 4.1 引脚图卡确认顺序
- 在孔里装上一个 5 针公头排针,或者准备好 PJRC 为 Teensy 3.6 和 4.1 出售的配套 USB Host 线
- 用细烙铁头和低温焊锡焊接,因为这是高密度板子上的小焊盘,粗烙铁头很容易把它们连锡
- 在充足的光线下检查每一个焊点。发暗、有颗粒感或者结成球状的焊点就是虚焊,这是主机端口什么都识别不到的最常见原因
- 通电之前,先用万用表的通断档检查 D- 和 D+ 之间有没有短路连锡
- 如果不用成品线而是直接飞线,D- 和 D+ 这对线要尽量短且长度一致,因为它是承载最高 480 Mbit/s 的差分对
- 不要随手把主机 5V 接到外部电源上,因为这路电源由板子自己控制通断,开关做限流是有原因的
需要哪些软件,文件在哪里
你需要 Arduino IDE 加上 PJRC 的扩展插件 Teensyduino。Teensyduino 自带主机库和 Teensy Loader,所以不需要再装别的东西。
# After installing Teensyduino, set these three in the Arduino IDE:
Tools > Board > Teensy 4.1
Tools > USB Type > Serial + Keyboard + Mouse + Joystick
Tools > CPU Speed > 600 MHz
# The host-side library ships with Teensyduino. Prove the hardware with its own example:
File > Examples > USBHost_t36 > Mouse
# USB identity is defined in the core, not in your sketch:
<arduino>/hardware/teensy/avr/cores/teensy4/usb_desc.h
<arduino>/hardware/teensy/avr/cores/teensy4/usb_names.h警告
如何刷写固件并测试主机端口
先刷写 USBHost_t36 自带的鼠标示例。它会把所接鼠标的每一次移动和点击都打印到串口监视器上,大约三十秒就能验证你的焊接有没有问题。测试之前要记住:主机焊盘上的 5V 电源是由芯片控制通断的,而不是直接接通的。如果板子上运行的固件从不启动主机库,插在主机端口上的鼠标连灯都不会亮。在这种板子上,主机端口看起来没反应说明不了任何问题。先刷写,再测试,最后才刷入你的辅助所要求的固件。
- 把 Teensy 的 micro-USB 设备端口接到你用来编译的电脑上
- 打开 USBHost_t36 的 Mouse 示例,按上面工具链设置中的说明设置 Board 和 USB Type,然后点击 Upload
- Teensyduino 会把编译好的镜像交给 Teensy Loader,由它重启板子并写入镜像。在未改动过的板子上,这个过程是自动完成的
- 如果上传卡住,按一下 Teensy 上的 Program 按钮。这会强制进入 bootloader,之后 Loader 就能找到板子
- 把一只有线鼠标插到刚焊好的主机端口上,打开串口监视器
- 移动鼠标。如果出现移动和按键事件,说明主机端口正常,硬件部分的搭建就完成了
- 接下来编译并刷写你的辅助文档中指定的透传固件,Board 和 USB Type 保持同样的设置
- 最后一次刷写完成后,给板子彻底断电再上电一次,不要只依赖软复位
按什么顺序接线
这个顺序一旦弄错,你很容易花上一个小时去排查一根线。设备端口朝向游戏主机,因为这一端要冒充鼠标;主机端口则朝向你的手。
- 把实体鼠标或无线鼠标的接收器插到 Teensy 焊好的 USB 主机端口上
- 把 Teensy 的 micro-USB 设备端口直接接到游戏主机的后置 USB 口上,不要经过集线器,也不要用前面板接口
- 从副机接出控制链路。它不能和设备端口共用,因为该端口的 USB 串口接口是在游戏主机上枚举的,也就是线插着的那台机器
- 改用八路硬件 UART 中的一路作为控制链路。在副机那一端接一个 USB 转串口适配器,这样两台机器永远不会共用同一根线
- 启动游戏主机,确认 Windows 中显示了一个鼠标设备,并且用手能正常移动光标
- 确认无误后,再启动副机上的软件并打开链路
提示
选择控制链路并配置辅助
复合 USB 类型可以在同一根线上同时提供鼠标接口和串口接口。但这个串口接口出现在插着设备端口的游戏主机上,副机根本打不开它。这还意味着,你实际玩游戏的那台机器上会多出一个与鼠标来自同一复合设备的串口设备,两个接口挂在同一个描述符下。所以控制链路应该改走硬件 UART,并在副机一端接一个普通的 USB 转串口适配器。这样游戏主机看到的就是一个纯粹的鼠标设备,多一根线、多一个配件,换来的是更干净的方案。无论用哪种链路,协议都由固件定义,辅助必须与之匹配。在辅助的输入设备菜单里你要设置三项:设备类型、COM 端口和波特率。设备类型通常显示为 Teensy 或通用串口设备;COM 端口是副机分配的那个;波特率是固件编译时设定的那个。三者必须一致。波特率不匹配不会报出明确的错误,因为连接能打开,只是什么都不做,看起来和设备坏了一模一样。所以要去设备管理器里确认端口号,如果辅助只能识别一位数的端口,就把它强制设到 10 以下;刷写时顺手把波特率记下来,不要事后再去猜。
回报率越高越好吗?
设备端口是 USB 高速接口,所以描述符可以请求比全速鼠标 1 ms 下限更短的间隔。实际效果就是亚毫秒级的回报,这正是大家喜欢这块板子的原因,但也正是在这一点上,热情往往超过了实际用处。回报率远高于游戏自身输入循环的处理速度,不会带来任何可测量的好处。而一个以不常见的速率保持完美规律的报告流本身就是一种特征,行为分析要找的正是这种特征。把回报率设成同类真实鼠标可能会用的数值。没有任何靠谱的基准测试能证明数字越高越安全,谁要是跟你报出一个具体的毫秒数,那都是他编的。
提示
如何修改 USB 描述符
因为固件是你自己编译的,厂商 ID、产品 ID、制造商和产品字符串、序列号以及 HID 报告描述符都由你掌控。如果不改,Teensy 呈现的是 PJRC 自己的身份,也就是一块开发板的身份,出现在一台本来没有任何理由接开发板的机器上。这些字符串和 ID 定义在核心库(core)的 usb_desc.h 和 usb_names.h 里,而不是在你的 sketch 里。4.x 核心库提供了一种更干净的做法:在 sketch 文件夹里单独建一个小的 C 文件来定义字符串描述符。一旦修改了厂商 ID 和产品 ID,Teensyduino 就无法再自动找到并重启板子,之后每次上传都需要按 Program 按钮。这是正常现象,不是变砖。动手修改之前先读描述符那篇指南,因为把真鼠标的身份抄得漏洞百出,比保持默认还糟。
Teensy 常见故障与解决方法
从上往下逐条排查。前四行覆盖了第一次搭建时的大部分问题,而这四个问题里有三个归根结底是焊接问题。
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 插在主机端口上的鼠标没有任何反应,鼠标上的灯也不亮 | 要么主机焊盘有虚焊,要么固件从不启动主机库,导致 5V 电源一直没有打开 | 先刷写 USBHost_t36 的 Mouse 示例。如果鼠标仍然毫无反应,把五个焊盘全部补焊一遍并检查通断 |
| 主机端口时而能识别时而不能,或者只有低速设备能用 | D- 和 D+ 这对线太长或长度不一致,或者焊盘之间残留了焊锡 | 缩短这对线并保持等长,或者换用正规的 USB Host 线。用异丙醇清洁焊盘,并在光线下仔细检查 |
| 游戏主机上完全没有出现鼠标设备 | IDE 中的 USB Type 不包含 Mouse,所以设备端口从不呈现 HID 鼠标接口 | 把 Tools > USB Type 设为包含 Mouse 的选项,重新编译、重新刷写,然后给板子断电重启 |
| 上传失败,或者卡在 Waiting for Teensy device | 当前运行的固件没有响应重启请求,或者你修改过厂商 ID 和产品 ID | 按一下板子上的 Program 按钮。修改过 VID 或 PID 之后,每次上传都要这样做 |
| 辅助能移动光标,但你自己的鼠标没反应 | 透传没有在运行:主机端不工作,设备端正常 | 用 Mouse 示例测试主机端口,因为原因几乎总是出在焊接上 |
| 你的鼠标能用,但辅助无法打开链路 | COM 端口选错,或者波特率与编译进固件的数值不一致 | 在设备管理器里找到该端口,设到 10 以下,并把波特率设为固件编译时使用的数值 |
| 移动粗糙、有台阶感,不够平滑 | 报告描述符使用的是 8 位移动字段,较大的位移量会被截断并拆成好几步发送 | 使用描述符声明为 16 位相对坐标轴的固件,并让辅助自己拆分大幅移动,而不是交给描述符去处理 |
| 板子发热,主机端设备在负载下掉线 | 所接设备的电流超出了主机端电源的限流值 | 换一只普通的有线鼠标,不要用 RGB 灯效繁多的鼠标或有源集线器,也绝不要在主机端口上接一个插满设备的集线器 |
Teensy 常见问题
能用 Teensy 4.0 代替 4.1 吗?
不太方便。4.0 的主机信号引出的是两个贴片焊盘,而不是五个带电源管理的通孔,所以你得自己手工飞线接 D- 和 D+,还要自己提供 5V。能做,但所有的指南和固件都默认你用的是 4.1。
必须用 PJRC 官方的 USB Host 线吗?
不是必须,但它是最省事的正确方案,因为它正好配 5 针排针,不费额外功夫就能把差分对接对。只要线够短、长度一致,手工飞线也可以。
Teensy 比 KMBox 更难被检测吗?
不一定。Teensy 给你的是控制权:描述符、字符串和回报率都由你决定,所以你可以呈现一个合理可信的身份,而不是默认身份。如果保持默认,它呈现的是开发板的身份,这比专门为此设计的设备更糟,所以控制权只有在你用上它时才是优势。
Teensy 自己能运行辅助吗?
不能,因为它没有任何办法读取游戏主机的内存。它只是按指令移动光标,往哪里移由 DMA 卡和副机决定。
无线鼠标的接收器插在主机端口上能用吗?
通常可以,因为主机会把接收器当作 USB HID 设备处理。但有些接收器会呈现额外的接口或私有的配置协议,透传固件会忽略这些,所以板载按键映射和部分软件功能可能会失效。
需要焊以太网 magjack 套件吗?
只有在你想用 IP 控制链路代替串口时才需要。副机就在游戏主机旁边时,串口更简单,还能省掉一次焊接。
刷错固件会怎样?
不会造成永久损坏。bootloader 在一颗独立的芯片上,按 Program 按钮总能让板子回到 Teensy Loader 可以写入新镜像的状态。所以 Teensy 很难因为刷写而变砖。
资料来源
我们核对过的来源清单中没有涉及 Teensy 本身的文档,因此板卡规格、焊接、刷写和故障表都来自实测。
- 01
继续阅读
仍然没有解决?在 Discord 提交工单
全部指南