1. 当AI开始画原理图:这件事到底靠不靠谱
第一次跟朋友提"让AI帮我画STM32最小系统原理图"这个想法时,对方回了一句:"你是想让它帮你画,还是想让它帮你把板子烧了?"这个反应其实挺有代表性的。在硬件圈子里,大家对AI辅助设计的态度一直是"能用但不敢全信",尤其是原理图这种一旦画错、后面PCB打样、焊接、调试全都要跟着遭殃的环节。
但实际情况是,STM32F103C8T6最小系统板这个东西,几乎是每个嵌入式工程师入门时都画过一遍的"标准答案"。它的电路结构高度固定:一颗MCU、一组去耦电容、一个复位电路、一个8MHz晶振加两个负载电容、一个BOOT跳线、一个SWD调试口、一个电源指示LED,再加上稳压部分。正因为结构足够标准化,它反而成了验证"AI能不能参与硬件设计流程"的绝佳试验田。
我这次做的事情,是用Claude Code作为执行代理,通过脚本化的方式去驱动嘉立创EDA专业版,把上面这套最小系统的原理图自动生成出来。整个过程不是"AI一键出图"那种营销话术,而是把原理图绘制拆解成一系列可编程的原子操作——放置元件、设置位号、连线、加网络标签、放电源符号——然后让AI根据一份结构化的电路描述去逐条执行。
这篇文章适合三类人看:一是想了解AI Agent怎么跟EDA工具打交道的硬件工程师;二是已经会用嘉立创EDA但想提升效率、减少重复劳动的人;三是对"AI+硬件"这个交叉方向好奇、想自己动手试一下的开发者。我会把整个链路的原理、踩过的坑、实际可复现的步骤都摊开讲,不藏私。
需要先说明一点:这套方案的核心价值不在于"省下画一张图的时间",而在于把重复性的、结构固定的原理图绘制变成可复用、可参数化的流程。你画一次STM32F103C8T6,下次换成F103C6T6或者加个CAN收发器,改几个参数就能重新生成,这才是真正省时间的地方。
2. 为什么选Claude Code + 嘉立创EDA这个组合
2.1 Claude Code在硬件脚本场景里的定位
Claude Code本质上是一个能读写文件、执行命令、调用工具的AI Agent。它跟普通聊天式AI最大的区别在于:它能真正"动手"——读你的工程文件、写脚本、跑命令、看结果、再修正。这个能力放到硬件设计场景里,就变成了一个"能理解电路意图、能生成操作脚本、能根据报错自我调整"的中间层。
我试过几种不同的AI参与方式。纯对话式让AI给网表,它给的元件参数经常是拍脑袋的,比如去耦电容给你写个0.5uF,晶振负载电容写个33pF却不告诉你这是针对特定CLK规格的。而用Agent模式,AI可以直接读到我提供的元件库文件、封装信息、引脚定义,输出的东西就有据可依。
Claude Code还有一个我很看重的特性:它能维护一个"上下文工程"。整个绘制过程中,它知道当前已经放了哪些元件、哪些网络已经连好、哪些还悬空。这种状态管理能力,是让自动化绘制从"玩具"变成"能用"的关键。
2.2 嘉立创EDA专业版的脚本接口能力
选嘉立创EDA专业版而不是其他工具,主要原因是它的扩展脚本体系相对开放。专业版支持通过JavaScript API去操作原理图文档对象,包括创建元件、设置属性、绘制导线、添加网络标签等。这意味着只要我能生成符合它API规范的脚本,就能程序化地完成绘制。
对比一下几个常见选择:
| 工具 | 脚本/自动化能力 | 元件库友好度 | 上手成本 |
|---|---|---|---|
| 嘉立创EDA专业版 | 支持JS扩展API,可操作原理图对象 | 立创商城库直接调用,封装齐全 | 中 |
| 某国外开源EDA | 支持Python脚本,生态成熟 | 库需自行维护 | 高 |
| 传统商业EDA | 部分支持宏命令 | 库庞大但授权复杂 | 高 |
嘉立创EDA专业版的优势在于,它的元件库跟立创商城的物料是打通的。我画STM32F103C8T6的时候,直接调用商城里的元件,封装、引脚、位号规则都是现成的,省掉了大量核对引脚的工作。这一点对自动化流程特别重要——如果元件库本身不规范,AI生成的脚本再准也没用。
2.3 这个组合真正解决的问题
说句实在话,如果只是画一张STM32F103C8T6最小系统,手动画也就一两个小时的事,用AI折腾脚本可能前期投入还更大。所以这个方案的价值点必须说清楚:
- 批量变体:同一套核心电路,换MCU型号、换晶振频率、加不同外设,参数化生成。
- 减少低级错误:位号重复、网络标签拼写错误、去耦电容漏放,这些人工容易犯的错,脚本化后基本杜绝。
- 知识沉淀:把"STM32最小系统该怎么画"这件事,从某个人的经验变成一份可执行的电路描述文件。
- 教学演示:给新人讲最小系统时,可以现场改参数、现场重新生成,比对着静态图讲直观得多。
提示:不要指望AI能替你完成"电路设计决策"。它擅长的是执行你已经想清楚的方案,而不是替你想方案。电源怎么分配、去耦电容放几颗、晶振走线怎么处理,这些还是得你自己定。
3. 让AI"看懂"电路:结构化描述文件的设计
3.1 为什么不能直接让AI自由发挥
我一开始的想法很天真:直接跟Claude Code说"帮我画一个STM32F103C8T6最小系统原理图",然后等它输出。结果它给出来的东西,元件是齐的,但连接关系全靠猜——VDDA和VDD它给你连一起了,NRST上的电容它放了个100nF(实际应该是100nF没错,但它没说明为什么),BOOT0它直接接地了却没提这是"从Flash启动"的配置。
问题出在:AI对"最小系统"这个词的理解是模糊的。它知道大概要放哪些东西,但不知道你的具体设计意图。所以正确做法是——先由人写一份结构化的电路描述,再让AI去执行。
3.2 电路描述文件应该包含什么
我最后定下来的描述文件格式是这样的,用JSON组织,分几个层次:
{ "project": "STM32F103C8T6_MinimalSystem", "mcu": { "part": "STM32F103C8T6", "package": "LQFP48", "power_pins": ["VBAT", "VDD_1", "VDD_2", "VDD_3", "VDDA"], "ground_pins": ["VSS_1", "VSS_2", "VSS_3", "VSSA"], "reset_pin": "NRST", "boot_pins": ["BOOT0", "BOOT1"] }, "power": { "input": "5V_USB", "regulator": "AMS1117-3.3", "output": "3V3" }, "decoupling": { "target": "3V3", "capacitors": ["100nF x4", "10uF x1"] }, "clock": { "type": "HSE", "frequency": "8MHz", "load_cap": "20pF" }, "reset": { "type": "RC", "resistor": "10k", "capacitor": "100nF" }, "debug": { "interface": "SWD", "pins": ["SWDIO", "SWCLK", "NRST", "3V3", "GND"] } }这份文件的关键在于:每个参数都有明确的物理含义,AI不需要"猜"。比如去耦电容写"100nF x4",AI就知道要放4颗100nF;晶振负载电容写"20pF",它就不会乱填。
3.3 描述文件到脚本的映射逻辑
有了描述文件,下一步是让Claude Code把它翻译成嘉立创EDA的API调用序列。这个映射关系需要提前定义好,我整理了一张对照表:
| 描述文件字段 | 对应EDA操作 | 注意事项 |
|---|---|---|
| mcu.part | 从库中检索并放置元件 | 需确认库中位号前缀为U |
| power.regulator | 放置稳压芯片 | 注意输入输出引脚方向 |
| decoupling.capacitors | 批量放置电容并连到电源网络 | 位号前缀C,需自动编号 |
| clock.load_cap | 放置晶振负载电容 | 容值需与晶振规格匹配 |
| reset.resistor | 放置复位电阻 | 位号前缀R |
| debug.pins | 放置排针或调试座 | 网络标签需与MCU引脚对应 |
这张表是整个自动化流程的"字典"。Claude Code拿到描述文件和这张映射表,就能生成对应的脚本。我实际用下来,映射表越细,生成结果越准。一开始我只写了"放置去耦电容",结果AI把电容全堆在一起没连线;后来改成"放置电容并连接到3V3和GND网络",它就知道要加网络标签了。
3.4 描述文件的版本管理
这一点很多人会忽略。电路描述文件应该跟代码一样纳入版本管理。我现在的做法是:每个项目一个描述文件,改动记录写清楚。比如从"8MHz晶振"改成"16MHz",描述文件里改一个字段,重新生成,diff一下就知道原理图哪里变了。
这样做还有个好处:当AI生成的图和你的预期不符时,你能快速定位是描述文件写错了,还是AI理解错了。如果是描述文件的锅,改文件;如果是AI的锅,调整映射规则或提示词。责任边界清晰,排查效率高。
4. 从零跑通:环境搭建与脚本生成实操
4.1 环境准备清单
在开始之前,你需要准备这些东西:
- 嘉立创EDA专业版:建议用较新版本,老版本的扩展API可能不完整。
- Claude Code:安装在你的开发机上,能访问本地文件系统。
- Node.js环境:因为嘉立创EDA的扩展脚本是JavaScript,本地调试需要Node。
- 一个空的EDA工程:新建一个原理图工程,作为脚本操作的目标。
安装Claude Code的过程这里不展开,官方文档写得很清楚。重点说一下配置:你需要让Claude Code能访问到你的工程目录和描述文件目录。我一般会在项目根目录放一个CLAUDE.md,里面写清楚这个项目的结构、描述文件位置、映射表位置,这样Claude Code一进来就知道该干什么。
4.2 第一步:让AI读取并校验描述文件
环境好了之后,第一件事不是直接生成脚本,而是让Claude Code先读描述文件,做一次"逻辑校验"。我用的提示词大概是这样:
读取 ./circuit/stm32_minimal.json,检查以下内容: 1. 所有电源引脚是否都有对应的去耦电容 2. 晶振负载电容是否与晶振频率匹配(8MHz通常配20pF) 3. 复位电路是否完整(电阻+电容) 4. BOOT引脚是否有明确配置 5. SWD调试口是否包含必要信号线 输出一份检查报告,列出缺失项和可疑项。这一步非常关键。我实测下来,AI在"校验"任务上的表现比"生成"任务稳定得多。它能发现一些我自己写描述文件时漏掉的东西,比如有一次我忘了给VDDA单独加去耦电容,它直接指出来了。
4.3 第二步:生成嘉立创EDA操作脚本
校验通过后,让Claude Code生成脚本。这里要注意,嘉立创EDA的API调用是有顺序要求的——必须先创建元件,再设置属性,最后连线。顺序错了会报错。
我让AI生成的脚本结构大致是这样的:
// 伪代码示意,实际API名称以官方文档为准 const eda = require('eda_api'); // 1. 放置MCU const mcu = eda.placeComponent('STM32F103C8T6', 'U1', {x: 200, y: 150}); // 2. 放置电源稳压 const ldo = eda.placeComponent('AMS1117-3.3', 'U2', {x: 100, y: 100}); // 3. 批量放置去耦电容 const capPositions = [ {x: 250, y: 100}, {x: 270, y: 100}, {x: 250, y: 120}, {x: 270, y: 120} ]; capPositions.forEach((pos, i) => { eda.placeComponent('100nF', `C${i+1}`, pos); }); // 4. 放置晶振及负载电容 eda.placeComponent('8MHz_Crystal', 'Y1', {x: 150, y: 200}); eda.placeComponent('20pF', 'C5', {x: 130, y: 220}); eda.placeComponent('20pF', 'C6', {x: 170, y: 220}); // 5. 连线与网络标签 eda.addNetLabel('3V3', {x: 250, y: 90}); eda.connectPins('U1.VDD_1', '3V3'); // ... 后续连接实际脚本比这个长得多,但结构就是这样。Claude Code会根据描述文件自动展开这些调用。
4.4 第三步:在EDA中执行并观察结果
脚本生成后,在嘉立创EDA的扩展脚本环境里执行。第一次跑大概率会报错,常见的有:
- 元件库中找不到指定型号(型号名拼写问题)
- 引脚名称不匹配(比如库里叫VDD,你写的是VDD_1)
- 坐标重叠导致元件堆叠
这时候不要慌,把报错信息贴回给Claude Code,让它修正脚本。我实测下来,一般迭代2到3轮就能跑通。这个过程本身就是"AI+人工"协作的典型形态——AI负责快速试错,人负责判断方向。
4.5 第四步:人工复核不可省略
脚本跑完,原理图出来了,但这不代表完事。必须人工复核。我复核的时候重点看这几项:
- 电源网络是否全部连通,有没有悬空的电源引脚
- 去耦电容是否都接到了正确的电源和地
- 晶振负载电容容值是否正确
- 复位电路极性是否正确(电容接VCC还是接GND,取决于复位芯片类型)
- 网络标签有没有拼写错误
有一次AI把"BOOT0"写成了"BOOT_0",网络标签对不上,导致BOOT0引脚悬空。这种错误肉眼扫一遍就能发现,但如果不复核,打样出来就是一块废板。
5. 那些让我熬夜的坑:位号冲突、引脚悬空与网络标签
5.1 位号自动编号的坑
嘉立创EDA在放置元件时会自动分配位号,但脚本批量放置时,如果不同时指定位号,它可能给你生成一堆重复的。我第一次跑的时候,4颗去耦电容全叫"C?",后面手动改了半天。
解决办法是在脚本里显式指定位号,并且用一个计数器保证唯一性。Claude Code生成的脚本里,我让它维护一个位号池:
const refCounters = { R: 0, C: 0, U: 0, Y: 0 }; function nextRef(prefix) { refCounters[prefix] = (refCounters[prefix] || 0) + 1; return `${prefix}${refCounters[prefix]}`; }这样每放一个元件,位号自动递增,不会冲突。这个逻辑看起来简单,但如果不提前设计,后面改起来很麻烦。
5.2 引脚悬空的隐蔽性
引脚悬空是最难发现的问题之一。原理图上看起来连线都连了,但某个引脚就是没接。AI生成脚本时,如果描述文件里没明确说某个引脚要接什么,它可能就跳过了。
我的应对策略是:在描述文件里强制要求每个引脚都有归属。要么接到某个网络,要么明确标记为"NC"(不连接)。然后在脚本里加一个校验步骤,遍历MCU所有引脚,检查是否都有网络归属。没有的就报错。
这个校验逻辑我让Claude Code写成了一个独立函数,每次生成脚本后自动跑一遍。实测下来,这个检查帮我抓出了至少三次引脚遗漏。
5.3 网络标签的命名一致性
网络标签是原理图的"神经系统",标签对不上,电气连接就是断的。AI生成标签时,容易出现大小写不一致、下划线位置不对、缩写不统一的问题。
我现在的做法是:在描述文件里定义一份网络标签字典,所有标签必须从字典里取。比如:
{ "net_labels": { "power_3v3": "3V3", "power_5v": "5V", "ground": "GND", "reset": "NRST", "boot0": "BOOT0", "swdio": "SWDIO", "swclk": "SWCLK" } }脚本里所有网络标签都通过字典引用,不直接写字符串。这样即使要改命名规则,改一处就行,不会漏改。
5.4 元件库型号匹配的坑
嘉立创EDA的元件库很庞大,同一个型号可能有多个版本(不同封装、不同厂商)。AI检索时如果只给型号名,可能匹配到错误的那个。
我的经验是:在描述文件里同时指定型号和封装。比如不写"STM32F103C8T6",而是写"STM32F103C8T6 + LQFP48"。这样匹配精度高很多。另外,对于常用元件,我会在描述文件里直接写立创商城的物料编号,这样最准。
5.5 坐标重叠导致元件堆叠
脚本批量放置元件时,如果坐标没算好,元件会叠在一起。原理图上看起来只有一个元件,实际上下面压着好几个。这个问题在后期DRC检查时才会暴露,排查起来很烦。
解决办法是:在脚本里实现一个简单的布局算法。我让Claude Code写了一个按功能分区放置的逻辑——电源部分放左上、MCU放中间、晶振放右下、调试口放右侧。每个区域内的元件按网格排列,间距固定。这样生成的原理图虽然不如手工布局美观,但至少不会重叠,而且结构清晰。
6. 生成之后:DRC检查与人工复核的配合
6.1 让AI先跑一遍自动检查
脚本执行完,先别急着看。让Claude Code调用嘉立创EDA的DRC(设计规则检查)接口,跑一遍自动检查。常见的检查项包括:
- 未连接的引脚
- 重复的位号
- 网络标签冲突
- 电源和地短路
AI拿到DRC报告后,可以自动分析哪些是误报、哪些是真问题。比如"未连接引脚"有时候是因为该引脚本来就该NC,这时候在描述文件里标记一下就行。
6.2 人工复核的重点清单
自动检查过了,人工复核还是要做。我整理了一份复核清单,每次生成后逐项过:
| 检查项 | 检查方法 | 常见问题 |
|---|---|---|
| 电源连通性 | 看电源网络是否覆盖所有电源引脚 | VDDA漏接 |
| 去耦电容 | 数数量、看容值、看连接 | 数量不足或容值错误 |
| 晶振电路 | 看负载电容容值和连接 | 容值不匹配 |
| 复位电路 | 看电阻电容值和拓扑 | 极性接反 |
| BOOT配置 | 看BOOT0/BOOT1电平 | 配置错误导致启动模式不对 |
| 调试口 | 看SWD信号线是否齐全 | 漏接NRST |
| 网络标签 | 逐个核对拼写 | 大小写不一致 |
这份清单看起来基础,但每次都能查出点东西。我印象最深的一次是VDDA的去耦电容漏了,自动检查没报(因为VDDA确实连到了3V3),但人工复核时发现VDDA和VDD共用了一颗电容,这在要求高的场合是不行的。
6.3 从原理图到PCB的衔接
原理图确认无误后,下一步是转PCB。这一步AI能帮的忙有限,因为PCB布局涉及太多工程判断——走线宽度、层叠结构、EMC考虑。但AI可以做一件事:检查原理图的网络表是否完整,确保转PCB时不会丢网络。
我一般会让Claude Code生成一份网络表摘要,列出所有网络及其连接的引脚。这份摘要跟原理图对照着看,能快速发现遗漏。
6.4 版本迭代时的回归检查
当你修改描述文件重新生成原理图时,一定要做回归检查。因为AI每次生成的结果可能有细微差异,上次没问题的这次可能出问题。
我的做法是:每次重新生成后,把新旧网络表做diff,看哪些网络变了。如果变化在预期内(比如就是改了晶振频率),那就没问题;如果出现了预期外的变化,就要查原因。
7. 这套流程真正省时间的地方在哪
7.1 从"画图"到"描述电路"的思维转变
用这套流程最大的收获,不是省下了画图的时间,而是强迫自己把电路设计意图写清楚。以前画图,很多细节是"脑子里有数,手上画出来",但没写下来。现在要写描述文件,每个引脚接什么、每颗电容放哪里,都得明确。
这个转变一开始有点别扭,但习惯了之后发现,它让设计过程更严谨了。而且描述文件本身就是一份最好的设计文档,后面维护、交接、复用都靠它。
7.2 批量生成变体电路的实测效率
我拿这个流程做过一次对比测试:手动画一张STM32F103C8T6最小系统,熟练的话大概90分钟;用这套流程,第一次搭建环境加调试花了差不多4小时,但之后每生成一张变体图,从改描述文件到复核完成,大概20分钟。
也就是说,从第二张图开始,效率优势就体现出来了。如果你经常需要画结构相似的电路(比如不同型号MCU的最小系统、不同外设的扩展板),这套流程的投入产出比很高。
7.3 适合和不适合的场景
适合的场景:
- 结构标准化的电路(最小系统、电源模块、常见接口电路)
- 需要批量生成变体的项目
- 教学演示和知识沉淀
不适合的场景:
- 高度定制化的模拟电路(AI对模拟电路的理解还很有限)
- 涉及高频、射频的电路(布局布线要求太高)
- 安全相关的电路(不能容忍任何不确定性)
7.4 我对AI辅助硬件设计的真实看法
用了这段时间,我的结论是:AI目前是"高效的执行者",不是"可靠的设计者"。它能把你已经想清楚的方案快速实现出来,能帮你检查一些低级错误,但它不能替你做设计决策。
所以正确的用法是:人负责"设计",AI负责"实现"和"检查"。这个分工下,效率提升是实实在在的。但如果指望AI从零帮你设计一个电路,那大概率会失望。
最后分享一个我踩过的坑:有一次我让AI"优化"一下去耦电容的布局,它把电容全挪到了MCU的另一侧,理由是"这样看起来更整齐"。结果走线变长了,去耦效果反而变差。从那以后,我明确了——布局相关的决策,AI只给建议,最终由人拍板。