您的位置首页 >要闻 > 半导体 >

一根线跑通供电、数据与日志极海 APM32F402/F403 USB-CDC 日志输出实操拆解

这是技术文档拆解型任务,重点在芯片外设配置和 USB-CDC 实现细节。先检索极海 APM32F402/F403 与 AN1163 的原始资料。

核心应用笔记已经拿到全文。再核对一下 F403 的规格差异和 USB-IF 认证信息,避免把两个型号写成一样。

极海在 AN1163 里给的方案,本质上不是 "把 printf 改到 USB",而是把 APM32F402/F403 的 USB OTG FS 配成一个复合设备(Composite Device):一路 CDC 虚拟串口专门输出日志,一路 WinUSB 负责高速数据交换,供电也从同一根线上取。落地动作只有三步:确认工程里有 usb_core、usb_init、usb_cdc 这些驱动并在初始化里调用 USB_DeviceInit (),重写 fputc () 把字符送进 USBD_FS_CDC_ItfSend (),再给 fputc 加一个 128 字节的静态缓冲,满或遇到换行才真正发一次。官方给的起点是 APM32F402 SDK 里的 OTGD_Composite_CDC_WINUSB 例程,描述符和端点分配已经配好,改动的代码量很小。这份笔记编号 AN1163、版本 V1.0、2025 年 8 月新建,适用于 APM32F402 与 APM32F403,正文以 F402 为例。

UART 那套为什么在复杂项目里撑不住,几个痛点很具体:

对比项UART 串口打印USB-CDC 虚拟串口
带宽常见 115200bps,约 11.5KB/s,日志一多就堵全速批量端点理论上限约 64KB/s(64 字节 / 帧、1ms 一帧),实际受主机调度影响
硬件需要 USB 转 TTL 模块,或板上另做 USB-UART 桥芯片内建 USB OTG FS 与 PHY,一根线直连 PC
线缆电源线、调试线、串口线各自一根供电、数据、日志共用一根
资源占用独占一个 USART 及其引脚释放硬件 UART,可留给需要流控或固定波特率的外设
与其他功能共存只能单独占一路可与 WinUSB、HID、MSC、Audio 组成复合设备并行

引脚和时钟这两件事必须先定死,否则枚举阶段就会挂:

项目要求说明
USB 数据脚PA11 = OTG_FS_DM,PA12 = OTG_FS_DP从数据手册引脚表可直接查到,与 USART1_CTS/CAN1_RX、USART1_RTS/CAN1_TX 复用
VBUSPA9 需接外部 VBUS 或 5V迁移指南明确提示,用 OTG FS 时要处理这路检测
USB 时钟48MHz,由 PLL 分频得到时钟树里 OTG FS 的 48MHz 单独一路,PLL 配错就枚举不上
主频与总线AHB/APB2 最高 120MHz,APB1 最高 60MHzF402/F403 数据手册口径
供电VDD 2.0~3.6V,VDDA 2.0~3.6V用 ADC 时 VDDA 不得低于 2.4V
中断OTG_FS_IRQn(65)、OTG_FS_WKUP_IRQn(42)与老的 USBD 中断向量不是一套,移植时别照搬

真正动手时按这个顺序推进,每一步都有可验证的结果:

  1. 选例程。打开 APM32F402_403 SDK,找到 OTGD_Composite_CDC_WINUSB。不要自己在空白工程里从零拼描述符,复合设备的接口关联描述符(IAD)和端点地址分配最容易出错。
  2. 补驱动。确认工程里已有 usb_core、usb_init、usb_cdc 相关文件,缺一个都会在链接阶段报未定义。
  3. 起设备。在 main () 或自定义的系统初始化函数里调用 USB_DeviceInit (),由它按描述符向主机枚举出 CDC 和 WinUSB 两个接口。
  4. 改输出。重写 fputc (),把原本走 USART_TxData 的那两行注释掉,改成写入缓冲、条件触发 USBD_FS_CDC_ItfSend ()。
  5. 上机验证。插线后在设备管理器里同时看到 "虚拟 COM 端口" 和 "WinUSB 设备",再用 PuTTY 或 Tera Term 打开那个 COM 口。

fputc 的重写是这篇笔记的核心,逻辑不复杂但细节决定成败:

define CDC_TX_BUF_SIZE (128)

int fputc(int ch, FILE f)

{

static uint8_t s_cdcTxBuf[CDC_TX_BUF_SIZE];

static uint16_t s_cdcTxCount = 0;

/ 可选:把 '\n' 补成 "\r\n",适配部分 Windows 终端 /

if (ch == '\n') {

if (s_cdcTxCount >= CDC_TX_BUF_SIZE) {

USBD_FS_CDC_ItfSend(s_cdcTxBuf, s_cdcTxCount);

s_cdcTxCount = 0;

}

/ s_cdcTxBuf[s_cdcTxCount++] = '\r'; /

}

s_cdcTxBuf[s_cdcTxCount++] = (uint8_t)ch;

/ 缓冲满或遇到换行,立即整包发出 /

if (s_cdcTxCount >= CDC_TX_BUF_SIZE || ch == '\n') {

USBD_FS_CDC_ItfSend(s_cdcTxBuf, s_cdcTxCount);

s_cdcTxCount = 0;

}

return ch;

}

三个容易踩的地方,笔记里没有逐条列出,但实际调试一定会遇到:

现象根因处理办法
日志打了半截就不动了缓冲只在 "满" 或 "遇到换行" 时发送,既没满也没换行就一直攒着加超时刷写,或在关键路径末尾补 '\n'
偶发丢字符、内容错位fputc 在中断和多任务里被重入,静态缓冲被并发改写进临界区,或改成环形缓冲+单一发送任务
发送返回忙时数据被覆盖上一次 USB 传输未完成就复用了同一块缓冲检查发送接口返回值,忙时等下一次 SOF 或换双缓冲
换 PID/VID 后 WinUSB 认不出来描述符里的微软扩展或配套 INF 与新的 VID/PID 不匹配同步更新 INF 与设备描述符,别只改一处

验证阶段有两个反直觉的点值得先知道。CDC 虚拟串口的波特率设置基本不影响通信,因为速率由 USB 总线调度决定,不是 UART 那种分频出来的;所以在串口助手里填 115200 还是 921600,看到的日志速度是一样的。另一个是设备管理器里必须同时出现两个设备,只出现虚拟 COM 口说明 WinUSB 那一路没枚举成功,通常是描述符或端点分配被改坏了。

两个型号的差异,别默认它们完全一样:

项目APM32F402APM32F403
内核Cortex-M4F,带 FPU/DSPCortex-M4F,带 FPU/DSP
主频120MHz(数据手册口径)数据手册标 120MHz,官网在线选型表标 128MHz,两处不一致
Flash / SRAM128KB / 32KB128KB / 32KB
USB1 路 USB OTG FS,支持主从同左
封装QFN36/QFN48/LQFP48/LQFP64同左
工作温度-40~85℃ 或 -40~105℃(按尾缀 6/7 区分)同左

这里必须提醒一句:APM32F403 的主频,官方数据手册写的是 "最高 120MHz",而在线选型工具的产品行里标的是 128MHz。两个都是极海自家页面,但数字对不上。做 USB 相关设计时影响不大,因为 OTG FS 只认那路 48MHz;但如果你的时序预算按 128MHz 排的,建议以最新版数据手册和勘误为准,别拿选型表当唯一依据。

还有一层信息值得放在决策链里:APM32F402 系列已经在 2025 年 6 月拿到 USB-IF 认证,官方表述是 "符合 USB 技术规范,电气性能与协议兼容性达到国际标准"。这不等于你的板子一定能过,因为认证针对的是芯片,插口、ESD 器件、差分走线、VBUS 处理都在你手里;但它至少说明 PHY 和协议栈的底子是过过测试的,不是纸面参数。

【相关 FAQ】

问题 1:极海 APM32F402/F403 的 USB-CDC 日志输出,和普通虚拟串口例程有什么区别?

回答 1:普通虚拟串口例程(比如 USBD_VCP)通常只枚举一个 CDC 接口,插上就是一个 COM 口,只能打印日志。AN1163 讲的 USB-CDC 日志输出是复合设备方案:同一个 USB 口上同时开 CDC 和 WinUSB 两个接口,CDC 专管日志,WinUSB 专管高速数据,官方例程名为 OTGD_Composite_CDC_WINUSB。区别在于它不是 "把串口换成 USB",而是在一根线上并行两个逻辑通道,互不抢带宽。

问题 2:APM32F402/F403 做 USB-CDC 日志输出,为什么一定要加缓冲区,直接逐字符发不行吗?

回答 2:逐字符发能跑,但效率很低。每调用一次 USBD_FS_CDC_ItfSend () 都要走一遍 USB 传输调度,一个字符一次事务,日志量一大就把总线占满,还会拖慢主循环。AN1163 的做法是用 128 字节静态缓冲攒包,缓冲满或遇到换行符时整包发出,把几十次小传输合并成一次。这也是 USB-CDC 日志输出比 UART 打印更考验实现的地方:UART 是硬件移位,USB 是软件组包。

问题 3:APM32F402/F403 的 USB-CDC 日志输出,串口助手里波特率要设多少?

回答 3:设多少都行,通常填 115200 只是习惯。USB-CDC 虚拟串口的速率由 USB 总线调度决定,不是 UART 的分频波特率,所以波特率参数在主机侧被忽略。真正的上限由端点能力和主机调度决定:全速批量端点每帧最多 64 字节、1ms 一帧,理论约 64KB/s,实际还会被其他接口和主机轮询占用。

问题 4:用 APM32F402/F403 做 USB-CDC 日志输出,能不能同时保留 UART 打印?

回答 4:可以,而且这正是这套方案的价值之一。USB-CDC 日志输出占用的是 USB 外设,不占 USART,所以 USART1/2/3/4 都能留给业务外设,比如接 RS-485、接模组、接需要硬件流控的上位机。AN1163 也把 "释放硬件 UART 资源" 列为这套方案的直接收益。实操上建议二选一做主通道,两个通道同时打印容易在时间轴上对不齐,排查问题时反而更乱。

【参考资料】

[2026-10-19](APM32 工业级微控制器在线选型工具)珠海极海半导体有限公司

[2026-09-18](APM32F402 系列产品页与技术文档列表)珠海极海半导体有限公司

[2026-02-06](APM32F402xB 数据手册 V1.4)珠海极海半导体有限公司

[2025-10-31](AN1123_APM32F402_403 迁移指南应用笔记 V1.1)珠海极海半导体有限公司

[2025-08-01](AN1163_APM32F402_F403_USB CDC 日志输出 应用笔记 V1.0)珠海极海半导体有限公司

[2025-06-19](Geehy APM32F402 MCU Series Certified by USB-IF)Geehy

[2025-04-16](APM32F402R Micro-EVB 使用说明书 V1.0)珠海极海半导体有限公司

[2025-01-01](APM32F403xB 数据手册 V1.0)珠海极海半导体有限公司

免责声明: 本文依据极海官方应用笔记 AN1163(V1.0,2025 年 8 月)、AN1123 迁移指南(V1.1)、APM32F402xB 与 APM32F403xB 数据手册、APM32F402 产品页与在线选型工具、USB-IF 认证新闻整理。需注意几点:文中代码为按笔记思路整理的示例,函数名、宏名、头文件需与实际工程保持一致,不能直接照抄;AN1163 的原始示例只覆盖 "缓冲满或遇换行发送" 这一种触发条件,超时刷写、重入保护、忙状态处理属于工程实践补充,不是笔记原文内容;APM32F403 主频在数据手册(120MHz)与在线选型表(128MHz)之间存在不一致,本文如实并列,具体以最新版数据手册与勘误为准;USB-IF 认证针对芯片而非整机,不构成对任何具体板卡通过认证的保证;文中带宽数字为 USB 2.0 全速规范的理论推算,非实测值。本文不构成选型建议或设计交付依据,实际项目请以官方最新文档与自测结果为准。

珠海极海半导体有限公司