搞嵌入式开发这几年,我踩过最大的一个坑就是:调试板子的时候,桌上永远缠着两根USB线,一根给JLink做SWD下载,另一根给USB转TTL做串口打印。直到有一天我仔细翻了JLink V9的原理图,才发现自己守着金矿还去讨饭——这家伙本身就内置了虚拟串口(VCOM)功能。只要正确启用,一根USB线就能同时跑SWD调试和串口通信,彻底告别USB转TTL。
这篇文章我会把JLink V9虚拟串口的原理、驱动、固件版本、使能步骤、接线方法、实战配置,以及最常见的SWD/JTAG Communication Failure问题全部摊开讲,保证你看完就能动手跑起来。
1. 先搞懂原理:JLink V9的虚拟串口到底从哪来
1.1 为什么JLink能当USB转TTL用
很多朋友拿到JLink V9,只关注SWD下载,从来没注意过板子上的TXD、RXD两个引脚。实际上,JLink V9内部有一颗主控芯片负责USB协议与JTAG/SWD协议的转换,这颗芯片里同时集成了一个USB转UART的桥接功能。也就是说,从USB协议层面看,JLink V9插上电脑后枚举出来的是两个设备:一个调试器接口(用来跑SWD/JTAG),一个CDC类虚拟串口(就是标准COM口)。这个虚拟串口在PC端看起来和你熟悉的CH340、CP2102没有任何区别,本质都是USB CDC设备,只不过它和SWD调试共享同一个USB物理接口。
我用生活类比帮你理解一下:USB转TTL相当于你专门雇了一个人,什么事都不干,只负责递纸条;而JLink V9相当于一个助理,既能帮你递纸条(串口收发),又能帮你传话指挥(SWD调试),而且这个助理只占用一个工位(USB口)。正因如此,一根线搞定两种功能在硬件上完全是可行的。
1.2 JLink V9虚拟串口相比USB转TTL的优势和局限
先说优势,这件事我实测了一整年,感受非常直接:
- 少占一个USB口:笔记本的USB口本来就紧张,拔掉USB转TTL之后,桌面清爽不少。对经常出差调试的人来说,这体验提升非常大。
- 少带一根线:USB转TTL模块本身也是成本,现在调试器和串口合二为一,包里少装一个小模块,野外现场少一次翻包找线的痛苦。
- 共用地线,少接一根线:USB转TTL如果单独用,需要额外把模块的GND和目标板GND接在一起;用JLink虚拟串口时,SWD的GND就是串口的GND,天然共地,减少了接线出错概率。
- 便于整体断电复位:拔插一次USB,调试器重新枚举,虚拟串口跟着一起重新初始化,现场排查问题时更利落。
但别以为虚拟串口能完全替代所有USB转TTL场景,有几个局限你得有预期:
- 流控引脚不全:多数JLink V9的虚拟串口只引出TXD、RXD、GND,没有CTS/RTS,所以硬件流控场景没法用。
- 波特率上限取决于固件:我实测常见的V9虚拟串口跑到921600是稳的,但再高就不好说了,USB转TTL某些型号能上1.5M甚至3M。如果你用115200或者460800,这个完全不是问题。
- 接线位置比较隐蔽:V9的TXD/RXD引脚通常不是标准20针SWD接口里的定义,而是板子侧面的排针或焊盘,不同版本的V9位置不一样,必须对着板子丝印找。
1.3 虚拟串口必须满足一个前提:固件里有VCOM功能
这里有一个很关键的知识点:JLink V9虚拟串口不是硬件上通电路就有的,它依赖固件。原厂SEGGER的正品V9固件是带VCOM功能的,所以插上就能看到COM口。但市面上流行的高仿V9和所谓“克隆V9”,固件来源五花八门,有些精简版固件为了降复杂度,把VCOM模块砍掉了,或者只在特定版本里保留。这就造成一个经典现象:同样是V9,别人插上有两个COM口,你插上只有一个调试器。
热词里经常出现的“jlink v9 614e.hex”,就是V9固件流传比较广的一个版本。根据我的实操经验,614e这个版本在不同来源的克隆V9上表现不完全一样,有的插上直接出VCOM口,有的需要手动在J-Link Commander里敲vcom enable,有的敲了也没反应。所以拿到一个V9,第一件事不是急着接线,而是先确认固件版本和VCOM是否可用。后面第3节我会给出完整的验证步骤。
2. 准备工作:驱动、软件、固件,一次配齐
2.1 安装J-Link软件包和驱动
使用JLink虚拟串口,我强烈建议安装完整的J-Link软件包,而不是只装一个驱动。SEGGER官方软件包里包含:
- J-Link调试器驱动(让系统识别调试器)
- J-Link CDC虚拟串口驱动(让系统识别COM口)
- J-Link Commander(命令行工具,用来启用VCOM、查固件版本)
- J-Flash(独立烧录工具)
- J-Link Configurator(图形化配置工具)
安装时注意,版本号会持续更新,但2024年以后的新版软件包默认都支持V9的虚拟串口枚举。装完之后,打开设备管理器,插上V9,理论上应该看到两类设备:一个是通用串行总线设备下的“J-Link”设备,一个是“端口 (COM和LPT)”下的“J-Link CDC UART Port (COMx)”。如果你只看到一个调试器设备而没看到COM口,先别急着重装驱动,大概率是固件或VCOM没启用,往下看第3节。
提示:如果你用的是Windows系统,碰到“设备描述符请求失败”或者“未知USB设备”的报错,优先排查USB线。JLink对USB线质量比较敏感,劣质充电线会导致枚举异常。我调试V9时换过三根线,最后用一根带屏蔽的短线才稳定识别两个设备。
2.2 确认固件版本和设备状态
在启用虚拟串口之前,先确认手头V9的固件是什么状态。打开J-Link Commander(安装目录下通常叫JLink.exe),连接目标板或者直接打开,命令行会打印当前固件版本号、硬件版本和序列号。比如常见的输出是:
SEGGER J-Link Commander V7.96 SN: XXXXXX Firmware: J-Link V9 compiled Dec 1 2023 10:30:00 Hardware: V9.40这个“Firmware”字段就是关键。如果固件版本太老,有些VCOM相关的指令可能不存在;如果固件是第三方精简版,甚至可能会提示“VCOM not supported”。所以看到版本信息后,先别急着干活,记下这个版本,然后验证VCOM支持情况。
2.3 关于固件版本与VCOM的关系,以及刷固件的风险
这里专门说一下网上流传的“614e.hex”这类固件。JLink V9因为停产和正品价格等原因,市面上存在大量兼容版/克隆版,它们用的固件大多来自网络流传的hex或bin镜像。614e这个版本在很多技术论坛里被讨论,原因就是它跟虚拟串口功能有直接关联。
根据我实际测试多块V9的结果:
- 如果固件版本中VCOM模块完好,插上就能枚举出“J-Link CDC UART Port”,设备管理器中直接多出一个COM口。
- 如果固件是精简版,J-Link Commander里输入
vcom enable会提示“VCOM not supported”或者干脆不响应。 - 部分特殊固件需要先进J-Link Commander执行一次
vcom enable,之后才会枚举出COM口,而且这个状态会一直保持。
如果你确认当前固件不支持VCOM,就需要考虑刷固件。但这里我必须提醒:刷固件有变砖风险,尤其是克隆V9,厂家的bootloader可能和原版不完全一致。我的建议是:
- 如果当前V9是正品,直接在J-Link Configurator里点升级固件,SEGGER官方会推送带VCOM的版本。
- 如果是克隆V9,先找对应的刷机教程和固件包,尽量找和你硬件版本匹配的。刷之前记录当前固件版本,万一刷挂了还能刷回去。
- 刷固件方式一般有两条路:通过bootloader模式(短接触发点后上电)使用SAM-BA或专用工具烧录,或通过J-Link自身的升级机制。具体操作根据你手上的固件包说明来。
我个人不建议新手一拿到V9就刷固件。先按第3节的方法测试一遍,如果虚拟串口能用,就别折腾。能用就别动,这是调试器最朴素的生存法则。
3. 启用虚拟串口:三步完成配置
3.1 用J-Link Commander打开VCOM
这里给出标准的启用流程。第一步,打开命令行,进入J-Link安装目录,运行JLink.exe。此时会出现一个命令行交互界面,通常会让你选择目标芯片型号和连接方式,如果只是启用VCOM,可以直接忽略或者随便选一个常见型号。
在命令行提示符下输入:
vcom enable如果固件支持,会返回类似VCOM enabled或者OK的提示。如果不支持,会报错或提示未知命令。执行成功后,必须重新拔插一次USB线,让设备重新枚举,VCOM口才会出现在设备管理器里。
第二步,重新插拔后,再次打开设备管理器,正常情况下“端口 (COM和LPT)”下会出现一个“J-Link CDC UART Port (COMx)”,这个COMx就是你的虚拟串口。
注意:
vcom enable这个命令是一次性配置,成功后状态会保存在调试器内部,下次插上直接就有COM口,不需要每次开机都执行。如果哪一天你发现虚拟串口消失了,先重新执行一遍这个命令。
3.2 管脚定义和接线方法
启用VCOM之后,剩下的事情就是硬件接线。关于JLink V9的TXD和RXD引脚位置,这里我要多说几句,因为很多人的接线错误就是死在这上面。
不同厂家的V9板子,TXD/RXD引出方式不一样:
- 有些V9在20针SWD接口旁边多了一个4针排针,丝印标着TXD、RXD、GND、VCC。
- 有些V9把TXD/RXD放在板子边缘,用测试点或小焊盘的形式。
- 还有一些V9的TXD/RXD直接复用在某个接口上,比如和SWDIO共用或和某些预留引脚相邻。
所以拿到V9后,第一步是拿出放大镜看板子丝印,找TXD、RXD、GND三个标记。找不到丝印就上论坛搜对应版本的引脚图,这个功夫不能省。
接线时请记住这个非常重要的对应关系(以STM32为例):
| JLink端引脚 | 连接目标 | 说明 |
|---|---|---|
| SWDIO | 目标板SWDIO | 调试数据线 |
| SWCLK | 目标板SWCLK | 调试时钟线 |
| GND | 目标板GND | 共地,同时也是串口参考地 |
| TXD | 目标板USART的RX引脚 | JLink发送,目标是接收 |
| RXD | 目标板USART的TX引脚 | JLink接收,目标是发送 |
注意,TXD要接目标板的RX,RXD要接目标板的TX。这是交叉接法,和USB转TTL模块的接法一模一样。很多朋友第一次接虚拟串口,直接把TXD对TXD、RXD对RXD,结果收到全空或乱码。
3.3 在串口助手里验证通信
接线完成后,打开任意串口调试助手(我用的是SSCOM和MobaXterm,都支持标准COM口)。选择你刚才看到的J-Link CDC UART Port对应的COM号,波特率先设115200或和你的目标板程序一致的波特率,数据位8、停止位1、无校验,打开串口。
这里有一个验证小技巧:如果目标板上电后没有主动打印数据,你可以把目标板的USART TX引脚配置成每1秒打印一次“Hello from STM32”,然后在串口助手里看是否收到。如果收到,说明虚拟串口到目标板的链路完全打通。如果完全没反应,按顺序排查:
- 波特率不一致(最常见)
- TXD/RXD接反(第二常见)
- 目标板串口初始化有问题(第三常见)
- JLink虚拟串口本身没启用成功(驱动或固件问题)
实操心得:验证虚拟串口是否可用,最简单粗暴的方法是先在J-Link Commander里执行
vcom enable,然后对比设备管理器在重新插拔前后有没有多出COM口。只要多出来,虚拟串口的USB链路就一定是好的,剩下的问题全在目标板那边。
4. 实战:一根线同时跑SWD调试和串口日志
4.1 一个STM32的完整接线与配置
为了让你能直接照抄,我给出一个完整的STM32F103使用JLink V9虚拟串口同时跑SWD和串口日志的实战配置。
目标板:STM32F103C8T6,使用USART1,PA9配置为TX(发送),PA10配置为RX(接收)。
硬件接线:
- JLink SWDIO -> STM32 PA13(SWDIO)
- JLink SWCLK -> STM32 PA14(SWCLK)
- JLink GND -> STM32 GND
- JLink TXD -> STM32 PA10(USART1_RX)
- JLink RXD -> STM32 PA9(USART1_TX)
这里没有接目标板VCC,因为STM32板子用USB口单独供电。如果你的板子是裸芯片,没有独立供电,可以从JLink的3.3V引脚引电源给目标板供电,但要确认目标板当前电压等级和JLink输出一致,否则可能烧芯片。
然后是代码部分,以Keil MDK + HAL库为例。初始化USART1:
void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } }然后重定向printf到串口:
int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); return ch; }主循环里每隔1秒打印一次调试信息:
while (1) { printf("SWD OK, UART virtual OK, count=%d\r\n", count++); HAL_Delay(1000); }编译下载后,你会发现一个很有意思的现象:Keil里用JLink跑在线调试,变量Watch窗口实时刷新,同时串口调试助手也在同步打印日志。整个过程中,PC端只插了一根JLink的USB线。
4.2 Keil里同时用调试器和虚拟串口
有些朋友会有疑问:Keil的调试器占用JLink的同时,虚拟串口会不会被顶掉?答案是不会。因为虚拟串口和SWD在USB协议层面是两个独立通道,就像同一个插座上插了台灯和充电器,互不影响。
Keil里配置JLink调试的方法很简单:
- 打开Options for Target -> Debug,选择“J-LINK/J-TRACE Cortex”。
- 点击右侧“Settings”,确认调试器识别到SW Device,并设置为SW模式。
- 下载或在线调试时,JLink命令窗口会正常打印连接信息。
实测下来,在线调试时我在主循环打了断点,然后去看串口助手的输出,发现最后一条数据停在断点前的位置,同时Watch窗口里的count变量和串口数完全对应。这说明调试器和虚拟串口真的在“肩并肩工作”。
关于调试器和虚拟串口同时使用,还有一个细节:JLink的虚拟串口不会因为进入调试状态而断开。即使CPU停在断点上,串口上已经发出的数据会完整到达PC端。但注意,如果你在断点处停留很久,后续的printf数据会堆积在串口缓冲区里,恢复运行后会突然冒出来一大串,这是正常现象,不是设备问题。
4.3 还能这么玩:在线调试时查看实时打印输出
如果你不想额外开一个串口助手,还有更骚的操作:Keil的Debug (printf) Viewer窗口可以配合JLink的虚拟串口使用。不过要注意,Debug (printf) Viewer标准用法是走SWO/ITM通道,和虚拟串口是两回事。如果你想把USART的数据直接在Keil里看,需要在“Options for Target -> Debug -> Settings -> Trace”中启用Trace功能,并把ITM通道和波特率配置正确。
这里我建议,日常调试用虚拟串口+独立串口助手,偶尔需要一个无干扰的纯日志窗口时才用ITM。因为虚拟串口的输出依赖USART外设,目标芯片的USART工作不正常时,虚拟串口也就废了;而ITM/SWO走的是调试通道,USART挂了也能看内核日志。两者互补,不要只依赖一个。
4.4 应用场景扩展:不只有STM32
虚拟串口的用法不限于STM32。最近我在一个FPGA项目里也这么干:FPGA逻辑里例化了一个UART发送模块,把FPGA的TX引脚接到JLink的RXD,PC端直接通过虚拟串口看FPGA内部状态寄存器的值。整个调试过程不需要额外的USB转TTL,也不需要单独的串口线。
另一个朋友在做基于K230的AI板卡调试时,直接把JLink虚拟串口当板卡的业务串口用——板子的主控串口输出应用日志,JLink SWD负责在线调试内核。对他这种USB口全插满的机器来说,省下一个口等于救了命。
实验、RS232、RS485这些场景也一样:只要你的目标板主控的UART是TTL电平,且引脚引出来了,就能和JLink虚拟串口对接。碰到RS232电平的设备,加一个电平转换芯片(MAX3232之类)即可。核心思路是一样的:把JLink的TXD/RXD当作一个标准的TTL串口来用。
5. 高频报错SWD/JTAG Communication Failure排查实录
5.1 先分清是SWD连接失败,还是虚拟串口失败
说句实话,虚拟串口本身很简单,真正让无数人头疼的是SWD报错。你电脑上明明装着JLink,Keil里也选了JLink,一连接就弹“SWD/JTAG Communication Failure”,心态直接炸。根据我这么多年的排查经验,这个报错的原因无非以下几类,按可能性排序:
| 原因 | 概率 | 现象特征 |
|---|---|---|
| 接线错误 | 高 | 某个引脚接触不良或接错,连接时无反应 |
| 目标板供电问题 | 高 | 目标板没电或电压不稳,JLink检测不到VTref |
| 复位电路或下载模式问题 | 中 | 目标主控被代码配置成低功耗或SWD引脚被复用 |
| 调试时钟速度太高 | 中 | 降低速度后能连上,默认速度不稳定 |
| 固件或驱动问题 | 低 | 换电脑/换JLink正常,本机一直失败 |
先说怎么快速定位:打开J-Link Commander,输入connect,如果JLink能识别出目标芯片的ID(比如Cortex-M3的IDCODE),说明SWD链路是通的,问题大概率在Keil配置层面;如果连IDCODE都读不到,那就是硬件连接问题。
5.2 接线与供电的经典坑
SWD接线我这里再啰嗦一次,标准接法:
- SWDIO、SWCLK是必接的两根信号线,方向别搞反。
- GND必须接,这个不用解释。
- 关键来了:JLink默认通过VTref引脚检测目标板电压。V9的目标板VTref如果检测不到电压,会直接拒绝连接或者报错。所以如果你只接了SWDIO、SWCLK、GND,没接VTref,而且目标板没有独立供电,那JLink会误以为目标板没上电。
解决方案有两种:
- 目标板独立供电,然后把JLink的VTref引脚接到目标板的3.3V电源引脚。
- 目标板不独立供电,直接把JLink的3.3V引脚接到目标板的VCC,同时VTref也接过去。
我推荐第一种,因为目标板独立供电时,调试器只负责信号,不参与供电,更安全。
5.3 代码把SWD引脚复用掉,导致进不了调试
这是嵌入式开发特有的坑。很多人写代码时为了省引脚,把PA13/PA14或PB3/PB4等SWD引脚复用成普通GPIO了。一旦代码烧进去,下次再连接调试器,SWD直接被禁用,JLink当然连不上。
解决方法是“Connect under Reset”:
- 在Keil的Debug Settings里,选择“Reset and Halt”或“Connect under Reset”。
- 在J-Flash里,打开Options -> Connection,勾选“Connect under Reset”。
- 硬件手法:按住目标板的复位键不松开,点击连接,在“正在连接”那个瞬间松开复位键。这个时机多试几次就有手感了。
如果目标板已经彻底跑飞,连复位都不好使,就用JLink的erase命令擦除整个Flash:
JLinkExe erase擦除前先确认JLink能读到IDCODE,如果读不到,还是得回到接线和供电排查。
5.4 虚拟串口不出现/打不开的排查
虚拟串口本身问题相对少,但也不是没有。我整理几个高频现象:
- 插上JLink后只有一个调试器设备,没有COM口:先确认
vcom enable是否执行成功。如果执行成功还是没有,考虑固件是否支持VCOM。多试几个固件版本,或者用J-Link Configurator升级固件。 - COM口出现但打开失败,提示被占用:虚拟串口和USB转TTL一样,同一时刻只能被一个软件占用。检查是不是有好几个串口软件同时开了,或者后台有程序(比如某些单片机的烧录监控软件)在监听COM口。我的习惯是先在任务管理器里把所有终端工具关掉,再重新打开。
- COM口号一直变,体验很差:这个其实很好解决,在Windows设备管理器里,右键点击J-Link CDC UART Port -> 属性 -> 端口设置 -> 高级,把COM端口号固定成一个不常用的数字,比如COM9或COM20。固定后以后每次插上都是同一个号。
- Linux下找不到JLink虚拟串口:Linux上一般会枚举为/dev/ttyACMx,如果没有重点检查udev规则。SEGGER官方文档里有Linux环境配置说明,这里不多展开。
5.5 虚拟串口乱码和波特率不稳的解决方案
如果你用虚拟串口收到的数据是乱码,或者时不时丢字节,先别怪JLink,按这四步排查:
- 检查波特率:目标板程序写的115200,串口助手就设115200;目标板用HSE时钟源且倍频不准,实际输出频率偏移,也会乱码。先用逻辑分析仪量一量目标板TX引脚的波形,确认实际波特率。
- 检查TXD/RXD接线:TXD和RXD交叉接了吗?接成平行线,数据像对暗号一样根本对不上。
- 降低波特率:如果目标板和JLink之间的杜邦线超过20cm,或者环境有电机、电源干扰,高速率下误码率会明显升高。把波特率降到38400或9600测试,稳定后再逐步提高。
- 换USB口:JLink别插在USB Hub上,尽量直连主机。我遇到过USB Hub供电不足,串口时好时坏,直连主板后完全正常。
实操心得:串口通信这种模块级联调,最容易忽略的就是“共地”。JLink虚拟串口虽然和SWD共用GND,但如果你目标板是通过另一个电源适配器独立供电的,而JLink接的是电脑USB供电,两者之间隔着电源隔离,串口一样可能工作异常。碰到诡异乱码,先把目标板和JLink的GND用杜邦线明确连一次,八成能解决。
最后再分享几个实际经验
折腾JLink V9虚拟串口这一年多,我总结下来最值钱的几条经验:
第一,拿到V9别着急写代码,先把虚拟串口跑通。确认它枚举出COM口之后,再在板子上写一个串口回环测试程序——把RX引脚收到的字节原样从TX发回去,然后在串口助手里发一串测试字符,能原样返回就说明硬件链路完全OK。这个小测试能帮你排除掉90%的接线问题。
第二,有条件的话,把V9侧面的TXD/RXD引脚直接焊上排针,用硅胶线做短跳线。很多V9自带的杜邦线接口在反复插拔后会接触不良,特别是TXD/RXD这种不太起眼的位置,一旦虚接,排查起来极其痛苦。
第三,如果你现在用的是JLink V9,又想尝试把日志输出改成ITM/SWO方式,请留好虚拟串口这条退路。ITM调试虽然方便,但要目标芯片支持SWO引脚且引出来才能用。在你没有百分百把握之前,虚拟串口永远是更稳妥的调试日志通道。
最后再提醒一句,JLink虚拟串口的启用状态是会跟着固件走的。如果你某天手贱点了J-Link Configurator的固件升级,升级完记得看一眼设备管理器,如果COM口不见了,重新执行一遍vcom enable,一切就都回来了。调试工具这东西,能稳定复现的操作就是好操作。