1. 一版板子回来,FDCAN 却完全“失声”:问题现场还原
STM32C092FCP6 这颗料我用了有一阵子了,一直以为 FDCAN 的重映射问题只会在别人的帖子里出现。结果这块板子贴片回来,第一次上电就给我上了一课:代码初始化全走绿,HAL_FDCAN_Start返回HAL_OK,HAL_FDCAN_AddMessageToTxMailbox也返回HAL_OK,可 CAN 总线上连一帧都看不到。
做嵌入式的人都知道,这种“软件全过、硬件无波”的情况最让人头疼。它不像烧录失败那么明显,也不是段错误崩溃那样立刻暴露,而是要带着示波器一步步去“捉鬼”。我在这块板上前前后后折腾了大半天,最后定位到的问题却是很多人都容易忽视的一个细节:FDCAN remapping。
1.1 硬件背景与最初的现象
先说一下这块板的硬件情况。主控是 STM32C092FCP6,TSSOP20 封装,LQFP48 开发板上那套外设引脚到了 20 脚封装上会砍掉很多,所以引脚分配必须重新设计。CAN 收发器用的是 MCP2562FD,一颗 CAN FD 收发器,总线侧按标准接了两个 120Ω 终端电阻,一个在板子靠近连接器处,另一个在对端测试设备里。
原本在 NUCLEO-C092RC 开发板上跑 FDCAN 环路测试,一切正常,发送、接收、错误计数都是干净的。于是我把同一份工程改了一下引脚分配,就发出去打样了。结果板子回来,刷上程序后,接上总线、用另一个节点持续发数据,这一端就像完全不存在一样——既不发送,也不应答,连 ACK 都看不到。
我用示波器点开板子到收发器之间的 TXD 引脚,电平一直停在隐性高电平,连一个下降沿都没有。用逻辑分析仪抓总线,CANH/CANL 同样是安静的。当时我心里就咯噔一下:这说明 MCU 压根没有把 FDCAN 的发送信号送出来,问题出在 MCU 侧,而不是总线侧。
1.2 快速排除:先把锅从硬件外围甩出去
遇到 CAN 不出波,我的第一反应是查外围,而不是查 MCU 配置。这个顺序很重要,因为很多人一上来就翻固件,最后往往浪费时间,其实问题就出在前级信号链路上。
我做了这样几件事:
- 量收发器的 VCC,3.3V 正常;
- 量收发器的 STBY 引脚,确认芯片不在待机或只听模式;
- 量总线上的终端电阻,本端 120Ω 正常,对端也有 120Ω,CANH 与 CANL 之间总阻值约 60Ω,符合 ISO 11898 的预期;
- 把收发器换了一颗新的,现象不变;
- 用另一个已知正常的 CAN 节点替换测试,现象依旧。
到了这一步,基本可以确定问题不是出在总线物理层,而是出在 MCU 到收发器这一段。也就是说,MCU 的引脚根本没有把 FDCAN 信号送出来,或者送出来的信号被错误的引脚路由截断了。
1.3 决定性的一个细节:原理图上接的是哪个引脚
排查到这里,我重新翻了原理图,才发现问题可能出在引脚选型上。PCB 布局时为了走线方便,我把 FDCAN1_TX 接到了 PB13,FDCAN1_RX 接到了 PB12。而在 NUCLEO 开发板上的测试工程里,FDCAN 用的是默认映射组的 PA11/PA12。
我最初以为只是 GPIO 配置没改,于是在 CubeMX 里把 PB12/PB13 的复用模式、AF 编号都选好了,重新生成工程,刷进去,结果还是没波形。这时候我才隐隐感觉到,问题没那么简单:很可能 C092 这颗芯片的 FDCAN 引脚不是“配好 GPIO 就能用”的,还需要额外的重映射开关。
2. FDCAN remapping 到底改了什么:C092 的引脚信号路由机制
在继续排查之前,我先把 C0 系列的引脚信号路由机制讲清楚。因为很多从 F1、F4 转过来的朋友,吃的最大的亏就是把“重映射”当成老一套,想当然地以为只要 GPIO 配置正确,外设就会正常工作。
2.1 C0 系列没有 AFIO,但 SYSCFG 里藏着重映射开关
STM32F1 时代有专门的 AFIO 寄存器,用来切换外设引脚。到了 F0/G0/C0 这一代,这个功能被并入了 SYSCFG 模块。C0 系列不像 F4 那样每个引脚都是“AF0~AF15 随便选”的通用矩阵,而是走了一条介于两者之间的路线:部分外设引脚既可以通过 GPIO 的 AF 编号来选择,也可以由 SYSCFG_CFGR1 里的外设重映射位来决定最终路由到哪一组引脚。
换句话说,对一个 FDCAN 引脚,C0 上实际存在两层选择:
- 第一层:GPIO 复用功能配置,也就是 MODER 选择复用模式、AFR 选择复用功能编号,决定这个引脚作为哪个外设功能组来工作;
- 第二层:SYSCFG 重映射开关,决定外设内部的某个功能信号(比如 FDCAN1_TX)最终送到哪一组引脚。
如果第二层没配置,即便你的 GPIO 已经选好了“这个引脚是 FDCAN 的”,芯片内部路由也没有把 FDCAN 输出连接到这个引脚上,结果就是引脚保持空闲状态,自然不来波形。
2.2 SYSCFG_CFGR1 里的 FDCAN1_RM 位
在 C092 上,FDCAN 相关引脚的重映射控制集中在 SYSCFG_CFGR1 寄存器中,其中有一个 FDCAN1_RM 位,专门用来选择 FDCAN1 的接收/发送信号走哪一组引脚。
这个位在参考手册里的定义大致是:
- FDCAN1_RM = 0:FDCAN1