PCB网表导入AI编程工具遇到的问题与思考

背景

在使用 AI 编程工具(Claude Code)辅助 STM32 嵌入式开发时,尝试让 AI 根据 PCB 网表文件自动生成硬件驱动代码(LED、按键等)。这个过程中遇到了一个典型问题:AI 无法从网表中正确推导核心板模块的 MCU 引脚映射,导致生成的驱动代码引脚配置错误。

本文记录了问题的发现、分析和解决过程,并对比了两种不同的 PCB 原理图绘制方式对网表可读性的影响。


为什么要导入网表

操作过程

在嵌入式开发中,软件工程师需要知道 PCB 板上每个外设(LED、按键、传感器等)连接到 MCU 的哪个 GPIO 引脚,才能编写正确的驱动代码。传统做法是查阅硬件原理图,手动查找每个连接。

使用 AI 编程工具时,我们希望通过以下流程实现自动化:

PCB 工程 (立创EDA/Altium/KiCad)
        │
        ▼
   导出网表文件 (.tel)
        │
        ▼
   AI 读取网表 → 解析连接关系 → 生成 PCB 连接关系表
        │
        ▼
   AI 根据关系表 → 自动生成驱动代码 (LED.c, KEY.c 等)
        │
        ▼
   编译 → 烧录 → 验证

具体操作步骤:
在这里插入图片描述

  1. 在 PCB 设计软件中导出网表:在立创EDA中,选择 文件 导出导出网表,生成 .tel 格式的网表文件
  2. 将网表文件放入项目目录:放到 Doc/ 文件夹下,供 AI 读取
  3. AI 解析网表:读取 $PACKAGES(元器件清单)和 $NETS(网络连接)两个关键段落
  4. 生成连接关系表:将二进制/文本格式的网表转换为人类可读的 Markdown 表格
  5. 基于关系表生成驱动代码:AI 根据引脚映射关系自动编写 GPIO 初始化和控制代码

将 PCB 工程转换为纯文本连接关系的意义

PCB 工程文件(如立创EDA的 .epro 文件)是二进制格式,只能用对应的 EDA 软件打开。将其导出为纯文本网表并进一步整理为 Markdown 连接关系表,有以下意义:

意义 说明
AI 可读 AI 编程工具无法直接解析二进制 PCB 工程文件,但可以读取纯文本格式的网表和 Markdown 文档
跨工具共享 不依赖特定 EDA 软件,任何文本编辑器都能查看
快速检索 可以用 grep 等工具快速查找某个引脚或网络的连接关系
文档化 Markdown 格式的连接关系表既是技术文档,也是 AI 的上下文输入

问题发现

一切看起来都很顺利——我把 PCB 网表文件交给 Claude Code,让它自动解析并生成 LED 和按键的驱动代码。编译通过,烧录成功,没有报错。

然而,当我把开发板接到电源上,期待地看着那几颗 LED 时,发现 LED1 和 LED2 死活不亮。我检查了代码,确认 GPIO 初始化没问题;我又检查了硬件,确认 LED 本身是好的。那问题出在哪?

我带着疑惑去核对了网表文件和 AI 生成的代码,才发现问题的根源:AI 对 U14 核心板引脚的 MCU 映射完全是猜测的,而且猜错了。

具体来说,网表里写的是:

D1 ; J1.10 LED1.1 U14.11

这一行告诉 AI:LED1 连接到了 U14 的第 11 号引脚。但 U14 是一个核心板模块,它的 11 号引脚对应 MCU 的哪个 GPIO?网表里没有说。AI 只能根据 STM32F103C8T6 的引脚排列去猜——结果猜成了 PA8,而实际上是 PB3

我对比了一下 AI 猜测的结果和实际引脚:

LED U14引脚 AI 猜测的MCU引脚 实际MCU引脚 结果
LED1 (D1) U14.11 PA8 PB3 错误
LED2 (D2) U14.10 PA11 PA15 错误
LED3 (D3) U14.9 PA12 PA12 碰巧正确
LED4 (D4) U14.8 PB15 PA11 错误

4 个 LED 引脚,AI 猜错了 3 个,只有 LED3 碰巧蒙对了。这就是为什么 LED1 和 LED2 不亮的原因——代码初始化的是 PA8 和 PA11,而 LED 实际接在 PB3 和 PA15 上。


问题根因分析

U14 是什么

U14 是一个 STM32F103C8T6 核心板模块(封装名为 CONN-TH_L53.3-W22.9_STM32F103C8T6-CARD),它是一个集成了 MCU、晶振、复位电路等的最小系统板,通过 40 个引脚的排针与底板连接。

关键问题:U14 的引脚编号(1-40)是核心板排针的物理排列顺序,与 STM32F103C8T6 芯片的引脚号(PA0-PA15, PB0-PB15, PC13-PC15 等)没有直接对应关系。

   U14 核心板(俯视图,示意)
   ┌─────────────────────────┐
   │  STM32F103C8T6          │
   │  ┌───────────┐          │
   │  │  MCU芯片   │          │
   │  └───────────┘          │
   │                         │
   └──┬──┬──┬──┬──┬──┬──┬──┬─┘
      1  2  3  4  5  6  7  8   ← 排针引脚编号
      对应哪个MCU引脚?需要查手册!

网表中有什么

原始网表文件中,对于 U14 的每个引脚,只记录了:

  • 连接到了哪个网络(如 D1KEY1$3N763
  • 连接到了哪些其他元件的引脚(如 J1.10LED1.1

没有记录这个 U14 引脚对应 MCU 的哪个 GPIO。


PCB 原理图网络命名方式对比

原始网表:功能名优先

在原始原理图中,我在绘制时先从外设端开始连线并命名。例如,LED1 的网络我先命名为 D1,然后再连接到 U14 核心板。
在这里插入图片描述

导出的网表片段(原始版 物联网竞赛版网表文件_Y31.tel):

; --- LED 网络 ---
D1 ; J1.10 LED1.1 U14.11
D2 ; J1.11 LED2.1 U14.10
D3 ; J1.12 LED3.1 U14.9
D4 ; J1.13 LED4.1 U14.8

; --- KEY 网络 ---
KEY1 ; C21.2 J2.11 R8.2 SW1.3 U14.30
KEY2 ; C22.2 J2.12 R9.2 SW2.3 U14.29
KEY3 ; C23.2 J2.16 R10.2 SW3.3 U14.25
KEY4 ; C24.2 J1.4 R11.2 SW4.3 U14.17

; --- 其他功能网络(无法得知MCU引脚) ---
$3N763 ; J1.9 U14.12              ← 自动生成名称,无法推导MCU引脚
$3N768 ; J1.8 U14.13
$3N919 ; J2.20 U14.21
$3N921 ; J2.19 U14.22
SG1 ; H11.2 J2.10 R25.1 U11.2 U14.31    ← 功能名,不知道是PA6
SG2 ; H17.3 J2.15 U12.3 U14.26          ← 功能名,不知道是PA1
UART2_TX ; J2.14 U9.7 U9.8 U14.27       ← 功能名,不知道是PA2
SCL ; H2.2 J1.7 U8.3 U14.14             ← 功能名,不知道是PB6

问题所在:

  • D1 ; J1.10 LED1.1 U14.11 — 只知道 U14.11 连接了 LED1,不知道 U14.11 对应 MCU 的 PB3
  • $3N763 ; J1.9 U14.12 — 自动生成的名称,完全无法推导 U14.12 对应 PB4
  • AI 只能根据 STM32F103C8T6 的标准引脚排列猜测映射关系,结果猜错了

修改后网表:MCU 引脚名优先

后来我修改了原理图,对于一些没有自定义功能名的网络,先从 U14 核心板引脚引出网络并命名为 MCU 引脚名

在这里插入图片描述

导出的网表片段(修改版 物联网竞赛板网表文件-修改版.tel):

; --- LED 网络(仍然是功能名) ---
D1 ; J1.10 LED1.1 U14.11
D2 ; J1.11 LED2.1 U14.10
D3 ; J1.12 LED3.1 U14.9
D4 ; J1.13 LED4.1 U14.8

; --- KEY 网络(仍然是功能名) ---
KEY1 ; C21.2 J2.11 R8.2 SW1.3 U14.30
KEY2 ; C22.2 J2.12 R9.2 SW2.3 U14.29
KEY3 ; C23.2 J2.16 R10.2 SW3.3 U14.25
KEY4 ; C24.2 J1.4 R11.2 SW4.3 U14.17

; --- 其他网络(现在是MCU引脚名) ---
PB4 ; J1.9 U14.12              ← 原来叫 $3N763,现在直接标 PB4
PB5 ; J1.8 U14.13              ← 原来叫 $3N768,现在直接标 PB5
PB6 ; H2.2 J1.7 U8.3 U14.14   ← 原来叫 SCL,现在直接标 PB6
PB7 ; H2.1 J1.6 U8.4 U14.15   ← 原来叫 SDA,现在直接标 PB7
PB8 ; J1.5 U14.16              ← 原来叫 $3N783,现在直接标 PB8
PA1 ; H17.3 J2.15 U12.3 U14.26  ← 原来叫 SG2,现在直接标 PA1
PA2 ; J2.14 U9.7 U9.8 U14.27    ← 原来叫 UART2_TX,现在直接标 PA2
PA3 ; J2.13 U9.5 U9.6 U14.28    ← 原来叫 UART2_RX,现在直接标 PA3
PA6 ; H11.2 J2.10 R25.1 U11.2 U14.31  ← 原来叫 SG1,现在直接标 PA6
PB10 ; H9.8 J2.6 U10.6 U14.35   ← 原来叫 UART3_TX,现在直接标 PB10
PB11 ; H9.1 J2.5 U10.5 U14.36   ← 原来叫 UART3_RX,现在直接标 PB11
PC13 ; J2.19 U14.22              ← 原来叫 $3N921,现在直接标 PC13
PC14 ; J2.18 U14.23              ← 原来叫 $3N923,现在直接标 PC14
PC15 ; J2.17 U14.24              ← 原来叫 $3N925,现在直接标 PC15
RESET ; J2.4 U14.37              ← 原来叫 $3N951,现在直接标 RESET
VBAT ; J2.20 U14.21              ← 原来叫 $3N919,现在直接标 VBAT

为什么 LED/KEY 网络名没变?

我后来尝试给 LED1 的网络也添加 PB3 标签,但网表中仍然显示为 D1。这是因为 立创EDA 有一个特性:网络名由第一个连接到该网络的网络标签决定

当我最初绘制原理图时:

  • LED1 网络:我先放置了 D1 标签,然后连到 U14.11 → 网表显示 D1
  • U14.12 网络:没有放置任何标签,EDA 自动生成 $3N763 → 网表显示 $3N763

当我修改原理图时:

  • LED1 网络:再添加 PB3 标签已经晚了,D1 已经是"全局网络名" → 网表仍显示 D1
  • U14.12 网络:我从 U14.12 引脚引出网络并放置 PB4 标签 → 网表显示 PB4

立创EDA 网络名优先级规则

通过这次实践,我发现立创EDA 的网络名遵循以下规则:

情况 网络名来源 网表显示
先放标签 D1,再连线 第一个标签 D1
先连线(无标签),再放标签 PB3 EDA 自动生成或第一个标签 可能是自动生成名
先从引脚引出并放标签 PB3 第一个标签 PB3

关键结论: 网络名取决于第一个放置并连接到该网络的标签。一旦确定,后续添加的标签不会改变网表中的显示。


正确的绘制方法

基于这个特性,正确的做法是:

在绘制原理图的最初阶段,就从主控芯片/核心板的引脚引出网络,并用 MCU 引脚名命名,使其成为全局网络名。
在这里插入图片描述
在这里插入图片描述

正确的绘制顺序:

1. 放置 U14 核心板符号
2. 从 U14.11 引脚引出导线
3. 立即放置网络标签 "PB3"
4. 再连接到 LED1、R15 等器件

错误的绘制顺序:

1. 放置 LED1
2. 从 LED1 引出导线
3. 放置网络标签 "D1"        ← 此时 "D1" 已成为全局网络名
4. 再连接到 U14.11
5. 后续再添加 "PB3" 标签    ← 无效,网表仍显示 "D1"

如果按正确顺序绘制,网表就会显示:

PB3 ; J1.10 LED1.1 U14.11     ← MCU 引脚名优先
PA5 ; C21.2 J2.11 R8.2 SW1.3 U14.30
...

这样 AI 就能直接从网表读出每个外设对应的 MCU 引脚,无需猜测或反推。


核心区别总结

绘制顺序 网络名结果 网表可读性 AI 解析难度
先从外设端命名(如 D1 功能名优先 低 — 不知道对应哪个 MCU 引脚 高 — 需要猜测或反推
先从 MCU 引脚端命名(如 PB3 MCU 引脚名优先 高 — 直接可读 低 — 直接可解析

对 LED 和 KEY 的影响

在我的原始原理图中,LED 和 KEY 网络是先从外设端命名(D1-D4KEY1-KEY4),所以网表显示的是功能名而非 MCU 引脚名。

问题关键: D1 ; J1.10 LED1.1 U14.11 这一行只告诉你 LED1 连到了 U14.11,不告诉你 U14.11 = PB3。

由于我在修改时才添加 MCU 引脚名标签,此时 D1 已经是"全局网络名",无法再改变。如果我在绘制最初就从 U14.11 引出网络并命名为 PB3,网表就会直接显示 MCU 引脚名。


最终确认的 U14 引脚映射表

结合方式二网表 + 用户手动确认,得到完整映射:

U14引脚 网络名 MCU引脚 功能
1 CS PB12 SPI Flash 片选
2 CLK PB13 SPI Flash 时钟
3 MISO PB14 SPI 数据输入
4 MOSI PB15 SPI 数据输出
5 BEEP PB1 蜂鸣器
6 DEBUG_TX PA9 串口TX
7 DEBUG_RX PA10 串口RX
8 D4 PA11 LED4
9 D3 PA12 LED3
10 D2 PA15 LED2
11 D1 PB3 LED1
12 PB4 PB4 扩展IO
13 PB5 PB5 扩展IO
14 PB6 PB6 I2C SCL
15 PB7 PB7 I2C SDA
16 PB8 PB8 扩展IO
17 KEY4 PB9 按键4
18 +5V 电源
19 GND 接地
20 VCC-MCU MCU 3.3V
21 VBAT VBAT 电池备份
22 PC13 PC13 LED0
23 PC14 PC14 扩展IO
24 PC15 PC15 扩展IO
25 KEY3 PA0 按键3
26 PA1 PA1 扩展IO
27 PA2 PA2 UART2 TX
28 PA3 PA3 UART2 RX
29 KEY2 PA4 按键2
30 KEY1 PA5 按键1
31 PA6 PA6 扩展IO
32 ADC1 PA7 ADC1
33 ADC2 PB0 ADC2
34 ADC3 PB1 ADC3
35 PB10 PB10 UART3 TX
36 PB11 PB11 UART3 RX
37 RESET NRST 复位
38 VCC-MCU MCU 3.3V
39 GND 接地
40 GND 接地

经验教训

对硬件工程师

  1. 绘制原理图时,优先从主控芯片/核心板引脚端命名网络:在立创EDA 中,网络名由第一个连接到该网络的标签决定。如果先从外设端命名为 D1,后续再添加 PB3 标签也不会改变网表中的显示。正确做法是从一开始就从 MCU 引脚端引出网络,并用引脚名(如 PB3)命名。

  2. 核心板模块的引脚编号 ≠ MCU 引脚号:这是一个常见的坑,尤其在使用第三方核心板时。网表只能告诉你"连到了模块的第几脚",不能告诉你"对应 MCU 的哪个 GPIO"。

  3. 考虑软件开发的便利性:如果原理图是为软硬件协同开发或 AI 辅助开发设计的,网络命名应优先使用 MCU 引脚名,而非功能描述名。

对 AI 辅助开发

  1. AI 无法"知道"硬件设计意图:网表中没有的信息,AI 只能猜测。在涉及硬件引脚映射时,必须提供明确的引脚对应关系。

  2. 纯文本格式是 AI 与硬件之间的桥梁:将 PCB 工程转换为 AI 可读的文本格式,是实现 AI 辅助嵌入式开发的关键步骤。

  3. 验证环节不可省略:AI 生成的驱动代码必须经过实际硬件验证,不能仅依赖编译通过。本次问题就是编译通过但硬件不亮的典型案例。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐