PCB网表导入AI编程工具遇到的问题与思考
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 等)
│
▼
编译 → 烧录 → 验证
具体操作步骤:
- 在 PCB 设计软件中导出网表:在立创EDA中,选择
文件→导出→导出网表,生成.tel格式的网表文件 - 将网表文件放入项目目录:放到
Doc/文件夹下,供 AI 读取 - AI 解析网表:读取
$PACKAGES(元器件清单)和$NETS(网络连接)两个关键段落 - 生成连接关系表:将二进制/文本格式的网表转换为人类可读的 Markdown 表格
- 基于关系表生成驱动代码: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 的每个引脚,只记录了:
- 连接到了哪个网络(如
D1、KEY1、$3N763) - 连接到了哪些其他元件的引脚(如
J1.10、LED1.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-D4、KEY1-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 | — | 接地 |
经验教训
对硬件工程师
-
绘制原理图时,优先从主控芯片/核心板引脚端命名网络:在立创EDA 中,网络名由第一个连接到该网络的标签决定。如果先从外设端命名为
D1,后续再添加PB3标签也不会改变网表中的显示。正确做法是从一开始就从 MCU 引脚端引出网络,并用引脚名(如PB3)命名。 -
核心板模块的引脚编号 ≠ MCU 引脚号:这是一个常见的坑,尤其在使用第三方核心板时。网表只能告诉你"连到了模块的第几脚",不能告诉你"对应 MCU 的哪个 GPIO"。
-
考虑软件开发的便利性:如果原理图是为软硬件协同开发或 AI 辅助开发设计的,网络命名应优先使用 MCU 引脚名,而非功能描述名。
对 AI 辅助开发
-
AI 无法"知道"硬件设计意图:网表中没有的信息,AI 只能猜测。在涉及硬件引脚映射时,必须提供明确的引脚对应关系。
-
纯文本格式是 AI 与硬件之间的桥梁:将 PCB 工程转换为 AI 可读的文本格式,是实现 AI 辅助嵌入式开发的关键步骤。
-
验证环节不可省略:AI 生成的驱动代码必须经过实际硬件验证,不能仅依赖编译通过。本次问题就是编译通过但硬件不亮的典型案例。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)