作为一个画过不少板子的硬件工程师,如果你到现在还在用单张原理图硬扛整个项目,那我强烈建议你花点时间把层次化原理图设计这套东西吃透。我见过太多人把三四百个器件堆在一张原理图里,密密麻麻的连线看得人头皮发麻,后期改一个信号名都要顺着蛛网找半天。这篇内容只讲一件事:在 Altium Designer(AD)里,怎么用层次化原理图把一个复杂的系统拆成逻辑清晰的模块,以及这套方法在实际项目里到底怎么落地。
文章会从设计思路、核心元素、完整实操到排错技巧一步步展开。不论你是从 PCB 小白往进阶走的爱好者,还是已经被复杂项目折腾到头疼的工程师,只要能在 AD 里画通一张简单的原理图,这篇内容里的操作你都能直接上手。
1. 层次化原理图设计:从“一张大图”到“一栋楼”
1.1 为什么你画到一半就想放弃
先说说没用层次化之前的状态。单张原理图本身没有错,它适合那种整套系统只有几十个元件、信号关系一眼能看穿的小板子,比如一个 Arduino 扩展板、一块简单的电源转接板。但一旦项目规模上来,单张图的问题就会暴露得特别明显。
最直接的问题是信号追踪。你想查一个控制信号从主控出来之后到底接到了哪个接口上,就要在密密麻麻的连线和网络标签里来回扫。看漏一根线,或者两个同名网络标签放得比较远,非常容易得出错误结论。然后是团队协作。两个人同时改一张原理图,光是协调文件谁在用就很麻烦,更别说每个人都往图里添东西,图纸很快就被改得面目全非。
还有一个经常被忽略的问题:设计复用。你花了很大精力画好了一个电源模块、一个通信接口电路,下个项目用得上却只能整个文件复制粘贴,然后删掉不相关的部分,再把网络一个个重新连好。一次两次还能忍,次数多了就是在消耗你的耐心。
层次化原理图解决的就是这三类问题。它的核心思路和写代码时拆函数一样,把一套完整系统按功能拆成若干个子模块,每个子模块对应一张独立的原理图,再在最顶层用方块图把这些子模块连接起来。整个项目的框架一目了然,信号流向清清楚楚,哪个模块出了问题直接进对应的子图去查,效率完全不一样。
1.2 一张图带你理解父图与子图的协作关系
层次化原理图里最基础的两个概念是父图和子图。父图也叫顶层图,通常只做一件事:放置方块图(Sheet Symbol),并通过方块图之间的连线把各个子模块的关系表达出来。子图则是真正画器件、连线、放端口的地方,每个子图对应一个具体的功能模块。
拿一套简单的温控系统举例。顶层图上有三个方块,一个叫 MCU,一个叫 SENSOR,一个叫 POWER。方块 SENSOR 的端口 TEMP_OUT 引出信号线,连接到方块 MCU 的对应端口 ADC_IN;方块 POWER 的端口 VCC_3V3 连接到 MCU 和 SENSOR 的供电端口。看到这张顶层图,你就知道这个系统的信号流是传感器采集温度、送给 MCU 做处理,电源模块给各模块供电。至于传感器具体用的什么型号、MCU 内部怎么配置引脚,那是子图里的事,不需要在顶层图里体现。
这种结构带来的直接好处是:任何一个子图都能独立阅读、独立修改。只要保证子图的端口和顶层方块图的对应关系不变,哪怕你在子图里把某个芯片从 STM32F103 换成了 GD32F303,对顶层图和其他模块来说都是透明的。这一点在项目迭代时价值极高。
1.3 两类设计流程,先搞清楚再动手
AD 的层次化设计支持两种创建流程:自上而下(Top-Down)和自下而上(Bottom-Up)。这两种方式没有绝对的优劣,取决于你习惯怎么思考问题。
自上而下的流程是先画顶层的方块图,规划好整个系统有哪些模块、模块之间怎么连接,然后让 AD 根据方块图自动生成子图的框架,你在子图里继续细化电路。这种方式适合从零开始的系统级设计,脑子里先有整体框架,再逐层落实到具体电路,思路非常顺畅。
自下而上的流程正好反过来:你先把各个子模块的原理图单独画好,验证没有问题,然后在顶层图里让 AD 根据已有的子原理图自动生成方块图,再把方块图的端口连起来。这种方式适合已经有成熟模块积累的工程师,比如手头有现成的电源电路、接口电路,把它们整合到新项目里,比从头画顶层图再逐步细化来得更快。
如果你刚开始接触层次化设计,我建议从自上而下入手,因为在没有子图约束的情况下,你会主动思考系统应该拆分成哪些模块、模块之间的接口怎么定义。这本身就是一种非常好的设计训练。等项目上经验多了,再回头看自下而上的方式,会觉得顺手很多。
2. 动手前的关键准备:端口、图纸符号与网络标识范围
2.1 层次化设计的三个核心元素
进入实操之前,有必要把 AD 里层次化设计涉及的几个核心元素说清楚。它们分别是端口、图纸符号和网络标签。很多人用不好层次化设计,根本原因就是对这三个元素的角色理解不到位。
端口是子图和父图之间传递信号的接口,画在子图的边缘上,好比硬件模块对外引出的排针。AD 里的端口放在菜单“放置 > 端口”下,放置后可以设置它的名称和 I/O 类型。端口的具体图形样式和方向箭头会自动根据 I/O 类型变化,比如输入端口箭头朝内,输出端口箭头朝外,非常直观。
图纸符号是顶层图上用来代表一个子图的矩形框,相当于在顶层图上贴了一张写着“这里是电源模块”的便签。图纸符号有两个关键属性:Designator 和 Filename。Designator 是这个模块在顶层图上的命名,比如 POWER_A;Filename 必须和你实际的子原理图文件名完全一致,AD 靠这个对应关系把方块图和子图关联起来。
网络标签的作用则要小心。在普通原理图里,两个同名的网络标签哪怕画在不同的位置,电气上是连通的。但在层次化设计中,这种“全局连通”的行为还有讲究,它受你设置的项目属性影响。简单说,如果你想让信号在子图之间传递,不能只靠网络标签同名,必须通过端口-图纸符号条目的路径走,否则很容易出现编译时信号没有连接的情况。
2.2 端口方向与命名规范
端口的方向是你给子模块定义的“契约”,直接决定了信号在模块之间怎么走。AD 里端口的方向一共有五种:输入、输出、双向、集电极开路和被动。实际使用中我一般只用前三种,集电极开路和被动更多地出现在特殊总线或模拟信号场景,普通数字系统用不到。
项目多人协同时,一定要对端口命名立规矩,不然每个人按自己的习惯起名,模块一多就乱套了。我的建议是:
- 端口名称使用大写加下划线,比如 MCU_UART_TX、PWR_5V,一眼能看出信号归属;
- 主动发起的一端定义为输出,接收的一端定义为输入;
- 所有子图对外端口的命名,必须和顶层方块图的图纸符号条目(Sheet Entry)名称完全一致,否则编译会报错。
曾经有一次,我把子图里一个端口命名为 EN_N,顶层方块图里对应条目创建的时候叫 EN,编译后信号直接断开了。这种问题非常隐蔽,因为它不会报太多 error,稍不留神就带着错误的连接状态进了 PCB。
2.3 Net Identifier Scope:决定信号跨图规则的开关
如果要选一个层次化设计里最容易被人忽视、影响却最大的设置,我首推 Net Identifier Scope。它在“工程 > 工程参数 > Options”里,选项有 Automatic、Flat、Hierarchical、Global 四种。
这组选项的核心作用:决定网络标签和端口在多个子原理图之间以什么规则连通。Automatic 是让 AD 根据工程内容自动决定,绝大多数情况选这个不会错。Flat 模式下,整个项目的所有网络标签都视为全局有效,端口的作用被弱化,同名的网络标签在任意子图之间都能导通。Hierarchical 模式下,网络标签只在当前图纸内有效,子图之间要通过端口和方块图来传递信号,这是层次化设计的标准逻辑。Global 模式则把端口和网络标签都强行视为全局连通,和 Flat 类似但更彻底。
新手最容易犯的错是:在子图 A 里放了一个网络标签叫 CLK,在子图 B 里也放了一个同名的网络标签,以为它们连上了,结果编译一看没有连接。原因就是在 Hierarchical 模式下,网络标签根本不跨图纸生效。要跨图传信号,必须把信号引出为端口,再在顶层方块图里连起来。
3. 完整实操:从顶层方块图到细节电路的落地流程
3.1 自上而下流程:先搭骨架再填肉
自上而下的第一步,是在工程里新建一张空白的原理图,命名成顶层图,比如 TOP.SchDoc。在这个顶层图里,执行“放置 > 图纸符号”,把方块图放到合适的位置。放置后双击方块图,在属性面板里把 Designator 和 Filename 填好。比如我想放一个“电源模块”的方块,Designator 填 PWR1,Filename 填 PWR.SchDoc。
下一步是关键:选中这个方块图,执行“设计 > 根据图纸符号建立子图”(Create Sheet From Sheet Symbol)。AD 会弹一个确认框问你是不是要创建子图,确认后工程里就会多出一张名为 PWR.SchDoc 的子原理图,并且子图里已经带好了脚标,脚标名称就是后续顶层方块图里要连线对应的条目名称。
在子图里把电路画完,回到顶层图,选中方块图,执行“设计 > 根据子图建立图纸符号条目”(Add Sheet Entry)或者直接放置菜单里的“添加图纸符号条目”,在方块图边缘添加端口条目。条目名称必须和子图里的端口名称完全一致,I/O 方向也最好保持一致。逐一把所有子图的端口条目都添加好,然后用导线把各个方块图的端口条目连接起来,顶层就完成了。
这个过程中最容易遗漏的就是“落地不干净”。很多时候方块图放好了,子图也生成了,但子图里某几个对外信号没有做成端口,而是用网络标签直接放着。顶层方块图这边自然也就不会出现对应的条目。编译的时候 AD 会给你报未解析信号的警告,这时候再回头补端口就有点手忙脚乱。建议在开始画子图之前,就先把所有对外信号的端口一次性建好。
3.2 自下而上流程:先画子模块再组装
自下而上与自上而下的操作路径正好相反。我先画好一个子功能原理图,比如 FAN_CTRL.SchDoc,在整个原理图里把对外的管脚都用端口画出来,命名规范,I/O 类型明确。等到这块子图的基础电路验证完成,我再新建顶层图,然后执行“设计 > 根据子图建立图纸符号”(Create Sheet Symbol From Sheet or HDL),在弹出的对话框里选择 FAN_CTRL.SchDoc,AD 就会自动在顶层生成一个方块图,并与这个文件关联好。
这种情况下,方块图的端口条目也会一并自动生成,不需要手动添加,非常省事。你要做的就是把各个方块图之间的条目连起来,形成一个完整系统。
自下而上最典型的应用场景是模块化产品线。比如你的公司做了好几款设备,都用到同一块电源板,电源板已经在老项目里验证过无数次。新项目只要把这个原理图文件纳入工程,在顶层图里执行“根据子图建立图纸符号”,就能把这块经过验证的电路作为模块引用进来。它带来的不只是省事,更是可靠性——复用的模块出过的问题已经被修掉了,你不需要重新担心它。
3.3 实例拆解:一个带 MCU 和电源域的小系统
把前面讲的流程串起来,我用一个简单系统举例:一套物联网节点板,包含一个 MCU 子系统、一个传感器接口和一个电源管理模块。
顶层图:我放了三个方块图。MCU_SYS 对应 MCU_SYS.SchDoc,SENS_IF 对应 SENS_IF.SchDoc,POWER 对应 POWER.SchDoc。在 POWER 子图里,我用 TPS62130 把输入电压转成 3.3V,输出端口叫 VCC_3V3,方向为输出。SENS_IF 子图里放置传感器的电平转换电路,端口有 VDD 输入、I2C_SCL 和 I2C_SDA 双向端口。MCU_SYS 子图里放主控芯片、晶振和启动配置,端口有 3V3、GND、I2C_SCL、I2C_SDA。
编译后,我在顶层图把 POWER 的 VCC_3V3 连到 MCU_SYS 和 SENS_IF 的 3V3 或 VDD,把 MCU_SYS 的 I2C_SCL 连到 SENS_IF 的 I2C_SCL,I2C_SDA 同理。信号流从电源、到 MCU、再通过 I2C 总线与传感器通信,层次一目了然。调试时如果发现 I2C 上拉电压不对,直接进 SENS_IF 子图查上拉电路就行,不用在整张图上找。
这个例子看着简单,但它完整覆盖了层次化设计的闭环:顶层定义架构、子图实现细节、端口完成接口。实物项目不管多复杂,本质都是这个套路在重复和叠加。
3.4 层次化对 PCB 布局的延伸价值:Room 分区
层次化原理图的好处不只停留在原理图阶段,到了 PCB 布局阶段还会继续发挥价值。原理图编译后,AD 会根据层次结构自动生成 Room。简单理解,Room 就是 PCB 上一个可以命名的区域,同一个子图里的器件会被划分到同一个 Room 内。
在 PCB 里导入网络表后,分配 Room 的器件仍然保留着属性。切换到 PCB 编辑器,执行“设计 > Room”,或者在 PCB 面板里选中某个 Room,你可以执行操作让对应的器件高亮,甚至一键把这些器件挪到布局区域内。这对复杂板卡的意义非常大:先按功能模块把板子分区,再在每个区域内做局部优化,比在整板上海底捞针式布局高效得多。
多通道设计也用得到这个特性。比如一个 8 路电机驱动板,8 路驱动电路的设计完全一样。AD 支持在多通道设计中用 Repeat 语法把某个方块图重复实例化,自动生成 Room_MOTOR0、Room_MOTOR1 等多组区域。PCB 布局时每一路的器件会自动落在对应的通道区域里,复制布局的工作量瞬间降下来。
4. 常见问题与排查技巧实录
4.1 常见问题速查表
实操中这些问题出现的频率最高,先列成表,方便你对照排查。
| 现象 | 可能原因 | 解决思路 |
|---|---|---|
| 编译提示 Not all nets were resolved | 网络标签跨图使用,但 Net Identifier Scope 是 Hierarchical,或子图端口未连到方块图 | 检查端口和方块图条目命名,确认 Net Identifier Scope 设置为 Automatic |
| 子图里端口和顶层方块条目对不上 | 端口名称大小写不同,或方向不一致 | 统一命名规范,核对 I/O 类型是否匹配 |
| 根据方块图生成子图后没有端口 | 用错了菜单,把方块图当成普通元件放置 | 应在方块图选中状态下执行“设计 > 根据图纸符号建立子图” |
| 编译报重复网络名 | 多个子图里使用了同名网络标签又设置了全局连通,或端口被重复连接 | 检查冲突的信号,把全局性的网络标签改为通过端口连接 |
| 方块图无法关联到已有原理图 | Filename 和实际文件不一致 | 双击方块图,核对 Filename 属性,重新指定正确的原理图文件名 |
| 某个端口信号在 PCB 里丢失 | 子图端口没有连接任何网络,或端口悬空 | 回到原理图,确认端口被导线有效连接,编译并查看未连接引脚报告 |
4.2 踩坑实录:那些编译后才发现的错误
第一个想重点说的问题是“端口悬空”。有一次我画一个子图,端口放在了原理图边缘,但我在子图内部漏画了引线,端口在网络表里没有连接到任何网络。编译时 AD 会报 warning,可我当时没细看 Messages 面板,直接导入了 PCB。直到生产回来后发现有一个引脚根本没法控制,才回头把这个端口连接问题揪出来。从那以后,我每次编译后都会花一分钟看一遍 Messages 面板里的 Warning 项,特别是带 Unconnected 字样的,绝不放过去。
第二个是“在方块图里改了端口名,子图没同步”。AD 的端口名和方块图条目名称是分别存储的,不会自动双向同步。手动改了方块图上的条目名称,子图里的端口名不会跟着变,编译必然报错。正确做法是选中子图的端口,右键执行“同步图纸符号条目”,或者统一从子图端口侧发起修改,再回到顶层检查。这个操作顺序问题很多人踩过,改名字一时爽,编译报错两行泪。
第三个比较隐蔽:工程的 Net Identifier Scope 设置成了 Flat,一切都正常连通,但你把工程发给同事,对方打开后他的 IDE 默认设置是 Hierarchical,结果报一堆未解析网络。这个问题的根源不在画图,而在工程文件里没有固化这个选项。建议在工程参数里显式设置好再去存放工程,不要依赖默认值。
4.3 多通道设计:用 Repeat 复用同一模块
多通道设计是层次化原理图的进阶玩法,核心思路是利用 Repeat 语法让同一个子图在编译时被多次实例化。比如一个 8 通道的模拟采集板,每个通道的电路完全一样,我没有必要画 8 张相同的子图,只需要画一张 ADC_CH.SchDoc,然后在顶层方块图里把 Designator 写成类似 Repeat(ADC_CH, 1, 8) 的格式。编译后 AD 会自动生成 8 个实例。
多通道的端口处理有点特殊。如果每个通道都有一路独立的信号,比如 CH1_IN、CH2_IN 到 CH8_IN,可以在方块图的条目里使用 Repeat 注释,让 AD 自动展开成多路。如果所有通道共享一个信号,比如时钟 SCLK,每个实例都会连接到这同一个网络,用普通条目即可。
多通道设计一开始会觉得抽象,操作起来也容易出错,但它带来的收益非常直接:改一个通道的电路,所有通道同步修改;PCB 布局时自动生成 8 组 Room,每一路都能独立放置和布线。如果你的产品天然具备这种重复性结构,这个技能值得花时间掌握。
4.4 提升调试效率的两个技巧
最后分享两个我用的顺手的技巧。第一个是“列表式检查所有跨图信号”。工程编译之后,执行“工程 > 工程选项 > 选项”里的“网络表”或“比较”功能,可以导出当前项目的网络连接清单。我会在导入 PCB 之前扫一眼这份清单,重点检查所有图纸符号条目的网络是不是都在预期范围内。这一步花不了两分钟,但能省下后面排查 PCB 的半天时间。
第二个是利用“导航”功能快速定位模块。子图和方块图关联后,在顶层方块图上右键选择“进入子图”,AD 会直接打开对应的子原理图,并定位到和该方块图相关联的位置。在主控芯片数据手册和原理图之间来回对照时,这个功能比手动翻文件树效率高得多。前期多用几次,你就会养成在顶层图里的“进出习惯”,看一个复杂项目的速度会明显变快。
我在实际项目中用层次化设计已经三年多,最大的体会是它改变的不仅是图纸的呈现方式,更是设计时候的思维方式。每一次新建工程,我都不再急着打开原理图摆元件,而是先在脑子里或者纸面上把系统拆成功能块,画清楚模块边界和信号接口。一开始这样做会觉得多了一步流程,但坚持下来之后,画图出错率明显下降,项目交接的时候给到别人的不只是一堆图纸,而是一套结构清晰的完整设计。如果你是刚开始接触层次化原理图,我的建议很简单:找一个小项目完整走一遍自上而下流程,再走一遍自下而上流程,把端口、方块图、编译检查这条链路彻底跑通。这个过程不会花你太多时间,但价值是长期的——后续做的每一个复杂项目,都会感谢你此刻的这一步投入。