用DAPLINK给STM32F103C8T6做虚拟串口这事,我最初是抱着试试看的心态搞的,结果发现这方案比我想象中实用太多。原来调试单片机总离不开USB转TTL模块,手边刚好没有的时候特别抓瞎,后来换了个带虚拟串口功能的DAPLINK下载器,一根USB线同时搞定下载、调试、串口通信,而且免驱动,省了一大堆装驱动的破事。这篇文章就把我折腾出来的经验完整写下来,从原理到接线到实操,再到各种坑,尽量一次讲透。
1. 为什么我推荐用DAPLINK做STM32F103C8T6的虚拟串口
1.1 串口调试在嵌入式开发中的核心地位
玩过STM32F103C8T6的朋友都知道,串口几乎是调试阶段的“生命线”。不管是打印日志、调试传感器数据,还是验证通信协议,都离不开一个可靠的串口通道。我最早用USB转TTL模块(比如CH340、CP2102那一类)来做这件事,虽然能用,但问题也很典型:一是要额外占用一个USB口,二是驱动偶尔抽风,换个电脑就要重新装,尤其是在别人机器上现场调试的时候,装驱动的过程非常影响效率。
STM32F103C8T6这块芯片本身就是入门首选,价格便宜、资源够用、资料多,但很多初学者在串口这一步就卡住了。老是听说“串口连不上”“识别不了COM口”“波特率对不上”“乱码”之类的提问,归根结底,很多人并不是不会用串口,而是被“驱动”这个拦路虎挡住了。DAPLINK下载器带虚拟串口功能,恰好能一次性解决这个痛点:下载程序、在线调试、虚拟串口三合一,而且免驱动插上就能用。
1.2 DAPLINK相比传统USB转TTL的核心优势
我之所以推荐DAPLINK而不是继续用USB转TTL,核心原因有几个。首先是“一线搞定”,DAPLINK下载器通过USB连接电脑后,同时会虚拟出一个串口和调试接口,不需要再接额外的串口线,也不用单独占用两个USB口。其次,DAPLINK是基于CMSIS-DAP协议的开源方案,调试功能对MDK、IAR、OpenOCD等都支持,兼容性非常广泛。
我用过的野火DAP下载器就是典型代表,它有标准版和精简版之分,标准版带虚拟串口功能,精简版砍掉了串口只保留下载调试功能,这个坑后面会专门说到。还有一个容易被忽视的点是,DAPLINK的虚拟串口在Windows 10和Windows 11系统下不需要装驱动,因为系统自带了HID和CDC的驱动支持,不像CH340那样偶尔还要担心驱动版本不对导致设备识别失败。安卓模拟器上vspd之类的虚拟串口软件,和DAPLINK这种硬件虚拟串口完全是两码事,别搞混了。
1.3 免驱动背后的门道:HID还是CDC
很多刚入门的朋友听到“免驱动版”可能会误解为“不需要任何驱动”,其实更准确的说法是“系统内置了对应的驱动”。DAPLINK的调试接口走的USB HID协议,而Windows系统天生支持HID设备,所以插上就能识别为“HID兼容设备”,不需要额外安装驱动。虚拟串口部分,常见有两种做法:一种是用USB CDC类协议,能被系统识别为标准的Communications and CDC Abstract Control Model设备,Win10/Win11直接识别为COM口(新装的Win10可能需要系统更新一下USB串行设备驱动);另一种是部分魔改固件把CDC也包装成HID方式,兼容性更广但性能和通用性稍差。
我实测过几款不同固件版本的DAPLINK,发现Win10下都能直接识别出“USB串行设备”,然后映射成一个COM口。这里要特别提醒,如果你用的是Win7系统,可能还是需要手动装一下驱动,Win7对CDC设备的支持不像Win10那么完善。所以带个Win10以上的电脑环境下,DAPLINK虚拟串口才是真正意义上的“免驱动”。
2. 动手前的准备:认清DAPLINK与STM32F103C8T6的硬件细节
2.1 DAPLINK下载器的引脚定义与版本区分
市面上常见的DAPLINK下载器外形五花八门,但引脚定义基本都遵循一个约定。一般情况下,下载器上会标有3.3V、5V(或者VCC)、GND、SWDIO、SWCLK、TXD、RXD、RST之类。SWDIO和SWCLK是用来连接芯片的SWD调试接口,TXD和RXD就是虚拟串口的收发引脚。
这里有一个非常关键的细节:虚拟串口引脚的连接方式。DAPLINK的TXD并不是直接接到STM32的TXD,而是接到STM32的RXD(PA10),DAPLINK的RXD接到STM32的TXD(PA9)。这种交叉连接方式很多初学者容易搞反,串口助手窗口里啥都收不到,还以为是程序写错了。
版本方面,需要注意区分“是否带虚拟串口”。很多便宜的精简版DAP下载器只引出了SWDIO、SWCLK、GND、3.3V、5V这几个脚,没有TXD和RXD,这种就不支持虚拟串口功能。我在淘宝上买过9块9包邮的,回来一看没有串口引脚,只好退掉重新买。所以下单前一定要看清楚商品详情页有没有标注“带串口”或“V2版本”。
2.2 STM32F103C8T6最小系统板的串口引脚
STM32F103C8T6最小系统板是目前非常流行的蓝色开发板,它默认的串口引脚是USART1的PA9(TX)和PA10(RX)。很多人会疑惑为什么是这两根引脚,因为STM32F103C8T6有多个串口,而USART1是最常用的调试串口,它可以通过内部引脚重映射,但默认情况下就是PA9和PA10。
另外,STM32F103C8T6的USART1和USB口(PA11、PA12)是独立的,所以即使你用了USB虚拟串口功能,也不会和DAPLINK的物理串口冲突。需要注意的是,如果你在代码里同时启用了USART1和USB,要注意引脚之间的关联,不过本文讲的方案不涉及芯片自带的USB,所以不用纠结这个问题。
最小系统板上通常已经集成了USB转串口电路,比如板子上的CH340芯片,但我推荐直接用DAPLINK的虚拟串口,而不是用板载的CH340。原因很简单:板载CH340需要另外插一根USB线,而且占用了开发板的USB口,接线变多容易乱。用DAPLINK的话,目标板只需要通过杜邦线接下载器,下载器和电脑之间一根USB线就够了,桌面清爽不少。
2.3 完整接线明细与供电注意事项
我用的是标准版DAPLINK下载器和STM32F103C8T6最小系统板,接线方式供参考:
| DAPLINK引脚 | STM32F103C8T6最小系统板引脚 | 说明 |
|---|---|---|
| SWDIO | PA13(SWDIO) | 调试数据线 |
| SWCLK | PA14(SWCLK) | 调试时钟线 |
| GND | GND | 必须共地 |
| 3.3V | 3.3V(可选) | 由DAP给板子供电 |
| TXD | PA10(RX) | 交叉连接,DAP发送到板子接收 |
| RXD | PA9(TX) | 交叉连接,板子发送到DAP接收 |
供电方面,如果目标板只是最小系统、没有大功率外设,DAPLINK的3.3V输出可以给板子供电。但如果你接了OLED屏、传感器、舵机之类的东西,乖乖用USB线或者外部电源给STM32F103C8T6单独供电,只和DAPLINK共地就好。我接过一个带ESP8266模块的项目,靠DAP的3.3V供电,Wi-Fi模块一发射就把电压拉低了,导致系统反复重启,查了半天才发现是供电不足的问题。
还要注意一个细节:DAPLINK的3.3V和5V输出能力有限,通常只有几十到几百毫安,给整个系统板供电时心里要有数。连接目标芯片后如果DAP下载器指示灯熄灭,八成是供电过载或者接线短路,这个后面专门讲。
3. 免驱动虚拟串口的原理与固件版本选择
3.1 从USB的角度理解“免驱动”这件事
要真正理解为什么DAPLINK的虚拟串口免驱动,得从USB设备分类说起。USB设备在枚举的时候会主动上报自己的“设备描述符”,告诉电脑自己属于哪个类别。CH340这种USB转串口芯片,用的是厂商自定义类别,Windows本身不认,所以必须装官方驱动才能识别成COM口。而DAPLINK的CDC虚拟串口,遵守的是USB通信设备类标准,Windows系统自带了usbser.sys这个驱动,所以枚举成功后就自动映射成COM口了。
我经常用这个类比来理解:USB CDC就像是USB生态里的“普通话”,Windows系统默认就会说这种“普通话”,所以不需要额外装“翻译器”。CH340用的厂商自定义协议更像是“方言”,Windows听不懂,你得给它装一个“翻译器”才行。所以DAPLINK免驱动的根本原因,就是它说的是设备类的“普通话”。
需要注意的是,老版本固件的DAPLINK可能枚举成一个HID设备和一个CDC设备,而CDC设备在极少数精简版Windows系统下还是会被标记成未知设备。遇到这种情况,先去Windows更新里补一下驱动库,或者手动指定usbser.sys驱动,一般就能解决。
3.2 固件版本对虚拟串口的影响
DAPLINK下载器的固件质量参差不齐,尤其是国产的各类翻版下载器,固件版本五花八门。我查过不少资料,发现国外有款基于SAML21的DAPLINK固件支持免驱动CDC串口,而野火官方早期固件的虚拟串口在某些Windows版本下也存在识别问题。
如果你手里的DAPLINK插上电脑后,设备管理器里只有“HID兼容设备”而没有“COM和LPT”下面的串口设备,那多半是固件里没有启用虚拟串口功能,或者固件版本太老。有些DAPLINK可以重新烧录固件来开启虚拟串口功能,但操作起来比较麻烦,还要用到另一个下载器,初学者不建议折腾。
我的建议是直接买固件支持虚拟串口的版本,比如带有“V2”“升级版”“带串口”标识的产品。买回来先插电脑看一眼设备管理器,确认出现COM口后再接线测试,省得后面出问题不知道是硬件还是固件的原因。
3.3 在设备管理器中确认虚拟串口正确识别
把DAPLINK插上电脑的USB口后,正常情况下的识别结果应该是:设备管理器里出现一个“HID兼容设备”(用于调试下载),同时“端口(COM和LPT)”下面出现一个“USB串行设备(COMx)”。这个COMx就是你的虚拟串口号。
我遇到过一种情况,设备管理器里能正常识别出两个设备,但MDK里下载程序的时候却提示找不到CMSIS-DAP调试器。后来发现是驱动被某些管家软件给优化“禁用”了,右键设备手动启用就好了。另外,如果你插了多个USB转串口设备,COM号可能会乱跳,每次烧录前在串口助手里确认当前的COM号,避免打开错误的串口。
如果设备管理器里有黄色感叹号,右键选择“更新驱动程序”,然后在“浏览我的电脑”里选择“从计算机的设备驱动列表中选择”,手动挑“USB串行设备”试一下。这个方法我用了不止一次,屡试不爽。
4. 实操全流程:从CubeMX配置到串口收发测试
4.1 CubeMX创建工程时的三个关键参数
我用STM32CubeMX配合Keil MDK来演示完整流程,这是目前最主流的开发方式。打开CubeMX后选芯片STM32F103C8T6,然后需要关注三个关键配置,缺一不可。
第一个是调试接口。在System Core > SYS > Debug里选择Serial Wire,这个必须设置,否则第一次下载程序后片内调试口被占用,第二次就连接不上芯片了。这个坑几乎每一个做STM32开发的人都踩过,所以配置时一定要记得。
第二个是USART1。在Connectivity > USART1里把Mode选为Asynchronous异步模式,参数保持默认的115200、8位数据、无校验、1位停止位即可。引脚会自动分配成PA9(USART1_TX)和PA10(USART1_RX),如果引脚被占用的话CubeMX会报冲突,这时候稍微调整一下相关外设的引脚分配就好。
第三个是时钟树。STM32F103C8T6最高主频是72MHz,默认情况下CubeMX会按外部晶振(HSE)自动配置。如果板子上没有外部晶振,你要把HSE关掉,用HSI内部时钟,但USART波特率精度会略差一点。我手里的板子一般都有8MHz晶振,所以我习惯用外部时钟,这时直接将HCLK设为72MHz即可。
4.2 MDK里配置DAPLINK下载与调试的步骤
CubeMX生成MDK工程后,打开项目,先别急着编译,先去配置调试器。点击Options for Target(魔术棒),在Debug选项卡里选择CMSIS-DAP Debugger,然后点旁边的Settings。正常情况下,CMSIS-DAP Adapter列表里会识别出你的DAPLINK下载器,Port选SW,Max Clock我一般设为1MHz(稳定优先),如果线材比较短、质量好,也可以用5MHz或10MHz。
这里有个小经验:如果点了Settings后识别不到设备,先别急着换下载器,看看是不是USB没插好,或者驱动被禁用了。另外,有些精简版的DAPLINK在MDK里识别为“CMSIS-DAP”或“ARM-CMSIS-DAP”,名称不同但功能一样。还需要把Flash Download选项卡里的Reset and Run勾上,这样烧录完成后芯片会自动复位运行程序,不用手动按复位键。接着就可以正常编译了。
第一次编译如果报错“Cannot load driver”,大概率是下载器驱动没正常加载。去设备管理器确认一下设备状态,如果一切正常还报错,试试换个USB口,尤其是台式机前置USB口经常供电不足导致识别失败,我用后面板的USB口基本没出过问题。
4.3 编译烧录与串口助手的收发验证
编译烧录这一步相对顺利,点LOAD按钮,DAPLINK的指示灯闪烁,然后就提示下载成功。最关键的是烧录完成后打开虚拟串口看现象。这里我写一段简单的测试代码,实现“收到什么就回什么”的环回功能,来验证串口通路是否正常。在main.c的while循环之前加一个发送字符串的逻辑,在stm32f1xx_it.c或main.c里加中断接收回调:
#include "main.h" #include "stdio.h" uint8_t rx_buffer; int fputc(int ch, FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); return ch; } void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART1) { HAL_UART_Transmit(&huart1, &rx_buffer, 1, 0xFFFF); HAL_UART_Receive_IT(&huart1, &rx_buffer, 1); } } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); HAL_UART_Receive_IT(&huart1, &rx_buffer, 1); printf("DAPLINK Virtual COM Test\r\n"); while (1) { } }这样重定向了printf到串口,同时在接收中断里把收到的字节原样发回去。编译烧录后,打开串口助手,选择DAPLINK虚拟出来的COM口,波特率设为115200。点“打开串口”,如果一切正常,马上就能收到“DAPLINK Virtual COM Test”这行字符串。然后在发送框里输入任意内容,点击发送,接收区会出现同样的内容,说明虚拟串口的收发都通了。
这里有个细节,串口助手的波特率必须和CubeMX里配置的波特率一致,否则收到的一定是乱码。我在测试时习惯先发一串“0x55”或者字母“U”,因为它的二进制是01010101,波形稳定,看波形更容易判断波特率偏差。
5. 常见问题与排查技巧实录
5.1 设备管理器识别异常与驱动残留
我遇到过的最尴尬的情况,是DAPLINK插上去完全没反应,设备管理器里连未知设备都不出现。这种情况一般是USB供电或线材问题,换一根数据线试试,注意有些USB线只能充电不能传数据,这个非常坑。我之前就用过一根看似完好的线,结果它只有电源线没有数据线。
还有一种情况是设备管理器里出现了两个“USB串行设备”,但你不知道哪个是DAPLINK的。可以用排除法:拔掉DAPLINK,看哪个COM号消失,那就是它的串口号。或者右键设备属性,看位置信息,通常能显示出插入的USB口位置。
如果你之前装过CH340或其他USB转串口的驱动,系统里可能存在驱动残留,导致COM号冲突。解决办法是在设备管理器里选择“显示隐藏的设备”,把旧设备挨个卸载掉,然后重新插拔DAPLINK。Windows会自动重新分配一个可用的COM号。
5.2 连接目标芯片后DAP指示灯熄灭怎么办
这是搜索热词里提得很多的现象:“dap下载器连接上芯片后灯熄灭,不连又恢复亮”。我拿这个问题专门分析过,基本可以锁定三种原因。
第一种是最常见的,目标板供电有问题,可能短路或者电流过大,把DAPLINK的3.3V引脚拉死了。DAPLINK给目标板供电能力有限,一旦目标板上有短路,下载器就会进入过流保护状态,指示灯熄灭。排查方法:把DAP和板子之间的3.3V连线断开,改用外部电源给板子供电,只保留SWDIO、SWCLK、GND三根线。如果灯恢复正常,那问题就在板子的供电上。
第二种是SWDIO和SWCLK接反了。这两根线颜色接近,有时候杜邦线一插就接错了。接反后通讯对不上,下载器反复尝试访问芯片,可能造成状态异常。用万用表量一下,或者重新仔细核对接线。
第三种是GND没接好或接触不良。别小看地线,SWD调试必须有共地才能工作,如果目标板是外部供电而没和DAPLINK共地,下载器一接上芯片逻辑电平就乱,指示灯也可能受影响。解决办法很简单:确保GND线接牢,而且最好用独立的一根杜邦线直接连接,不要共用一根母对母跳线转好几个弯。
5.3 能下载程序但虚拟串口一直没有输出
这种情况在带虚拟串口的DAPLINK上比较常见。能下载程序说明SWD调试通道是好的,虚拟串口没输出说明串口通路有问题。按照这个思路排查:先检查TXD、RXD接线是否交叉接对,再检查CubeMX里USART1有没有正确使能,然后检查程序里有没有真正执行串口发送函数。
我写代码时偷懒直接用HAL_UART_Transmit阻塞发送,发送一个长字符串有时候会卡在主循环里,虽然不影响收发,但实时性很差。后来改用中断方式或DMA方式传输数据,效率高很多。如果只是测功能,用阻塞发送就够了,但要注意不要在一个死循环里反复发送,否则发送缓冲区会把CPU卡死。
另一个容易忽略的点是“虚拟串口只发不收”。有些DAPLINK固件默认只支持调试下载,虚拟串口是单向的或者需要特殊设置才打开。我手里的野火DAP就有一个硬件跳线帽或者固件配置项,用来切换串口模式,具体要看产品手册。
5.4 串口乱码与收发失败的排查
串口出现乱码,先确认波特率是否一致,这是排在第一位的原因。其次是时钟配置不正确,如果CubeMX里HCLK配置错误,导致USART的波特率计算有偏差,收发也会出乱码。尤其是用了内部时钟HSI的时候,精度不够,长时间通信容易积累误差,建议用外部晶振。
我实测过,如果CubeMX里把HSE设为External Clock Source(外部时钟源),但板子上没有外部晶振,芯片实际跑在内部时钟上,造成主频和配置不一致,串口波特率就会有较大偏差,接收乱码甚至完全不收。这种情况把HSE改为关闭状态,或者使用一个真实的外部晶振就好。
收发失败还有一种隐蔽原因:USART1的PA9、PA10引脚上接了其他外设,导致电平被拉低。我试过在PA9上接了一个LED,结果串口发送的波形被LED的寄生电容影响,高电平上不去,接收端全是乱码。拔掉LED后恢复正常。所以排障时要把该引脚的外部负载全部断开,用示波器看波形最直观。
5.5 常见问题速查表
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| DAP插上电脑无任何反应 | USB线只能充电、USB口供电不足 | 换数据线、换后置USB口 |
| 设备管理器有未知设备或感叹号 | Windows驱动库不全,驱动未正确加载 | 手动更新为“USB串行设备”驱动,或系统更新 |
| MDK无法连接CMSIS-DAP | 驱动被禁用、下载器USB识别失败 | 设备管理器启用设备,重新插拔 |
| DAP连接芯片后灯熄灭 | 目标板短路、供电过载、接线错误 | 独立供电、检查线路、核对SWDIO/SWCLK/GND |
| 能下载但不能串口收发 | TX/RX接反、固件无串口功能 | 交叉接线、使用带串口的DAP固件 |
| 串口乱码 | 波特率不一致、时钟配置错误、外部负载干扰 | 对照配置、检查晶振、断开引脚负载 |
| 下载器连接稳定但经常掉线 | USB供电不足、线材质量差、电磁干扰 | 换短而粗的线、换USB口、远离强干扰源 |
6. 几个实用小建议(来自我的实际体会)
最后分享几个只有亲手折腾过才会注意到的小技巧。第一,DAPLINK的虚拟串口和板载CH340完全可以共存,你可以在CubeMX里同时开启USART1和USART2,把两个串口分别接到不同的调试通道上,方便对比调试。第二,使用带隔离的DAPLINK下载器在调试电机驱动这类大功率电路时,能避免很多共地噪声带来的干扰,如果常做电机控制类的项目,可以考虑入手一个。
第三,虚拟串口的COM号是可以固定的。在设备管理器里右键属性,端口设置的高级选项里修改COM端口号,就能把DAPLINK固定到一个你习惯的COM号,省得每次插拔后COM号乱跳。第四,如果只是把程序下载到板子里,不用在线调试,DAPLINK还能用U盘拖拽的方式烧录新版本固件,直接二进制文件拖进弹出的U盘就完成下载,非常方便。
另外再提一句,STM32F103C8T6的国产替代型号在市场上很常见,引脚和性能基本兼容,DAPLINK下载器的使用流程完全一样,不用担心芯片换国产就没法用。我自己就屯了一批国产版做批量测试,下载调试一切正常。
这个方案对我日常开发效率的提升非常明显,你不用再为驱动发愁,不用再带一堆线材和模块,一个DAPLINK全搞定。如果你手里的DAPLINK本身就带虚拟串口功能,赶紧按我说的这套流程试一遍,把串口调试这块彻底打通,后面做项目会顺手很多。