
1. 为什么文件名靠不住Gerber层校验的底层逻辑做PCB设计的朋友大概率都遇到过这种场景板厂发来一封邮件说您的Gerber文件里缺少阻焊层或者丝印层和钢网层搞反了然后你打开文件夹一看文件名明明写着GTS、GBS、GTO看起来一切正常。问题出在哪出在文件名只是一个标签它不携带任何关于文件内部实际内容的强制约束。Gerber格式正式名称是RS-274X现在也有X2版本本质上是一种描述二维图形数据的矢量格式。它告诉光绘机或CAM软件在某个坐标画一条线、填充一个区域、闪一个焊盘。文件本身并不包含我是顶层阻焊这样的语义信息。我们平时看到的*.GTL、*.GBL、*.GTS、*.GTO这些扩展名完全是CAD软件比如Altium Designer、KiCad、Cadence Allegro在导出时按照自己的命名习惯生成的属于约定俗成而非格式强制。这就带来一个很现实的问题如果有人手动重命名了文件或者用了不同软件导出的文件混在一起或者导出时层映射配置错了文件名和实际内容就会脱节。我见过最离谱的一次是同事把顶层线路层和底层线路层导出后文件名写反了板厂也没仔细看直接按文件名做结果整批板子报废。所以校验Gerber层必须穿透文件名去看文件内部的图形数据本身。那怎么看内部核心思路是通过分析每一层图形的几何特征、坐标范围、孔径定义、极性设置反推它到底是哪一层。比如阻焊层通常是负片逻辑开窗处不覆盖绿油它的图形表现为焊盘周围的空洞丝印层是正片表现为文字和边框线条钢网层和焊盘形状高度一致但通常比焊盘略小或等大。这些特征才是判断层属性的可靠依据。注意Gerber X2标准引入了%TA和%TO属性字段可以携带层功能信息但现实中大量文件仍是旧版RS-274X没有这些属性。所以不能依赖X2属性做校验必须做几何分析。2. 从文件头到尾Gerber文件里真正值得读的字段要写一个靠谱的层校验工具或者哪怕只是手动排查都得先搞清楚Gerber文件里哪些字段是有信息量的。很多人打开Gerber文件一看全是坐标数字就头大其实结构很清晰我按重要性排个序。2.1 格式声明与单位第一道校验关口文件开头通常会有%FSLAX36Y36*%这样的格式声明。FS表示格式规范LA表示前导零省略、绝对坐标后面的X36Y36表示整数位3位、小数位6位。紧接着是%MOMM*%或%MOIN*%声明单位是毫米还是英寸。这两个字段为什么重要因为如果同一套Gerber里有的层用毫米、有的层用英寸那叠层对位必然错乱。我写校验脚本时第一步就是提取所有层的单位和格式声明做一致性比对。曾经遇到过一块板子顶层线路是毫米底层线路是英寸原因是导出时两个层用了不同的输出配置。这种问题光看文件名根本发现不了。2.2 孔径定义AD命令层的指纹之一%ADD10C,0.500000*%这样的语句定义了D码10是一个圆形孔径直径0.5毫米。不同层的孔径集合往往有显著差异。比如线路层孔径种类多有各种宽度的线宽、各种尺寸的焊盘。阻焊层孔径通常比线路层焊盘大0.05-0.1mm开窗补偿且很少有细线径。钢网层孔径和焊盘接近但通常没有线路层那些用于走线的细孔径。丝印层孔径以细线为主常见0.15mm、0.2mm这类线宽。通过统计每层的孔径分布可以初步判断层的类型。比如某层如果只有0.15mm和0.2mm两种圆形孔径且数量很多那大概率是丝印层。2.3 坐标范围与图形密度空间分布特征提取每层所有坐标点的最小/最大X、Y值可以得到该层的包围盒。正常情况下线路层、阻焊层、丝印层的包围盒应该基本重合都覆盖整个板子。如果某一层的包围盒明显偏小或偏移那就有问题。图形密度也很关键。我一般会计算单位面积内的绘制命令数量。丝印层因为文字多命令密度通常很高阻焊层因为是大面积开窗命令相对少但单条命令覆盖面积大线路层介于两者之间。2.4 极性LP命令负片还是正片%LPD*%是正片%LPC*%是负片。传统上内层电源/地平面常用负片阻焊层在某些软件里也用负片逻辑。但现代导出习惯更倾向于全部用正片然后通过图形本身表达。如果发现某层混用了正负片或者阻焊层用了正片但图形是实心大块那就要警惕了。3. 手把手写一个层校验脚本从解析到判定光讲原理不够我把自己常用的校验流程拆成可复现的步骤。这里用Python举例因为生态好、库多实际上你用任何语言都能做核心是解析逻辑。3.1 解析Gerber的最小可行代码不需要完整的Gerber解析器我们只提取关键信息。下面这段代码可以提取单位、格式、孔径定义、坐标范围import re def parse_gerber_header(filepath): with open(filepath, r, errorsignore) as f: content f.read() info {} # 提取单位 unit_match re.search(r%MO(MM|IN)\*%, content) info[unit] unit_match.group(1) if unit_match else UNKNOWN # 提取格式 fs_match re.search(r%FSLAX(\d)(\d)Y(\d)(\d)\*%, content) if fs_match: info[format] fX{fs_match.group(1)}.{fs_match.group(2)} # 提取所有孔径定义 ad_matches re.findall(r%ADD(\d)([A-Z]),([\d.]), content) info[apertures] [(int(d), shape, float(size)) for d, shape, size in ad_matches] # 提取坐标范围简化版只抓X和Y的数值 coords re.findall(rX(-?\d)Y(-?\d), content) if coords: xs [int(c[0]) for c in coords] ys [int(c[1]) for c in coords] info[bbox] (min(xs), min(ys), max(xs), max(ys)) return info这段代码很粗糙但足够做初步筛查。实际生产中你需要处理坐标的缩放根据FS声明的小数位数以及处理G01、G02、G03等插补命令。3.2 用孔径特征做层分类拿到每层的孔径列表后可以设计一个简单的分类器。我常用的规则如下特征线路层阻焊层钢网层丝印层孔径种类数多10中5-15中5-15少1-3最小孔径可能很小0.1mm通常0.2mm通常0.2mm0.1-0.2mm最大孔径大焊盘大开窗大开窗小线宽孔径形状圆、矩形、椭圆圆、矩形圆、矩形几乎全圆这些规则不是绝对的但组合起来准确率能到80%以上。剩下的20%需要结合坐标范围和图形密度进一步判断。3.3 坐标范围交叉验证把每层的包围盒画出来对比。正常情况下线路层、阻焊层、丝印层的包围盒应该几乎完全重合。如果某层的包围盒比其他的大了一圈那可能是机械层或者外形层混进来了。如果某层的包围盒明显偏小那可能是某个子区域被单独导出了。我遇到过一个案例客户发来的Gerber包里有一个文件叫Top_Silk.GTO但它的包围盒只有板子左上角一小块。打开一看原来只导出了板子上的一个Logo丝印其他丝印都没导。这种问题文件名完全看不出来但包围盒一比对就露馅了。4. 实战中那些文件名骗过我的案例理论讲完了说几个我亲身踩过的坑。这些案例的共同点是文件名看起来完全正常但内容对不上。4.1 案例一扩展名对调板厂没发现有一次我负责一个四层板项目导出Gerber后交给板厂。板厂回复说您的顶层阻焊和底层阻焊文件是不是反了我打开一看文件名是Board_GTS.gbr和Board_GBS.gbr看起来没问题。但用脚本一分析GTS文件的孔径特征和底层线路层完全匹配GBS和顶层线路层匹配。原来是我在Altium导出时层映射表里把Top Solder和Bottom Solder的勾选搞反了。这个问题的根因是Altium的导出配置里层名和输出文件名是两套独立的映射。你在Layers选项卡里勾选的是实际要导出的层但在Output Files里可以自定义每个文件的名字。如果这两处不一致就会产生文件名说它是顶层阻焊实际内容是底层阻焊的情况。4.2 案例二丝印层混入了装配层内容另一个项目板厂反馈丝印层上有一些奇怪的方框像是元件外框。我检查了GTO文件发现里面确实有元件轮廓线。问题是这些轮廓线本应该只在装配层Assembly Layer出现不应该在丝印层。原因是导出时丝印层和装配层用了同一个输出配置把装配层的图形也包含进去了。这种问题的检测方法是看丝印层里有没有大面积的矩形或复杂多边形。正常的丝印层主要是文字、极性标记、1脚标识元件外框通常用细线表示但如果出现填充的矩形块那就要怀疑是不是混入了其他层的内容。4.3 案例三钢网层和阻焊层搞混钢网层Paste Layer和阻焊层Solder Mask Layer在图形上非常相似都是焊盘的开窗。区别在于钢网层用于制作锡膏印刷钢网它的开窗通常和焊盘等大或略小阻焊层用于制作绿油开窗通常比焊盘大0.05-0.1mm。如果导出时把钢网层和阻焊层搞混板厂按钢网层做阻焊会导致绿油开窗偏小焊接时焊盘被绿油覆盖无法上锡。检测方法是对比同一位置的焊盘尺寸。如果某层的开窗尺寸和线路层焊盘完全一致那它更可能是钢网层如果比焊盘大一圈那更可能是阻焊层。5. 把校验流程固化从手动到自动化手动排查一次两次可以但项目多了肯定受不了。我的做法是把校验逻辑固化成一个脚本每次导出Gerber后自动跑一遍输出一份校验报告。5.1 校验报告应该包含什么一份实用的校验报告至少要有以下内容层清单列出所有Gerber文件以及脚本推断出的层类型。一致性检查单位是否统一、格式是否统一、包围盒是否对齐。异常标记哪些层的特征和文件名不符哪些层可能缺失。建议对于可疑层给出具体的排查建议。我通常会把报告输出成Markdown表格方便直接贴到项目文档里。5.2 集成到导出流程中如果你用Altium可以通过OutJob文件配置导出后的后处理脚本。如果你用KiCad可以用Python脚本调用kicad-cli导出后再跑校验。关键是要让校验成为导出流程的必经环节而不是事后补救。提示校验脚本不要追求100%准确它的价值在于发现异常而不是自动修复。发现异常后仍然需要人工确认。5.3 一个容易忽略的细节文件编码和换行符Gerber文件通常是ASCII文本但有些软件会输出带BOM的UTF-8或者用Windows换行符。如果你的解析脚本没处理好这些可能会漏掉文件开头的格式声明。我建议在读取文件时统一用errorsignore并手动去除BOM。6. 当文件名和内容冲突时该信谁这个问题看似简单但实际决策时很多人会犹豫。我的原则很明确信内容不信文件名。文件名只是给人看的标签内容才是板厂真正会用来生产的数据。但这里有一个例外如果文件名和内容冲突而你又无法确定哪个是对的那就停下来重新导出。不要试图手动重命名文件来修复问题因为重命名不会改变文件内容只会让问题更隐蔽。我见过有人发现GTS和GBS内容反了就把两个文件重命名对调以为解决了。但实际上如果导出配置本身就是错的重命名只是掩盖了问题下次导出还会错。正确的做法是回到CAD软件检查层映射配置重新导出。另外和板厂沟通时不要只说文件名是什么要说我校验过这个文件的实际内容是某某层。板厂的CAM工程师通常有经验你提供的信息越准确沟通效率越高。7. 进阶用X2属性做辅助校验虽然不能依赖X2属性但如果文件恰好有那它就是最强的校验依据。Gerber X2的%TF.FileFunction%属性可以直接声明层功能比如%TF.FileFunction,Copper,L1,Top*%表示顶层线路。我的做法是优先读X2属性如果没有再走几何分析。这样既利用了新标准的便利又兼容了旧文件。def get_layer_function(content): # 尝试读取X2属性 tf_match re.search(r%TF\.FileFunction,([^*])\*%, content) if tf_match: return tf_match.group(1) return None如果X2属性和几何分析结果冲突那说明文件本身可能有问题需要人工介入。8. 一些零散但有用的经验最后分享几个小技巧都是实际工作中攒下来的。第一导出前先做一次空跑。在CAD软件里把所有层都关掉只打开你要导出的层看看屏幕上显示的是什么。这比事后校验更直接。第二保留一份黄金参考。对于经常做的板型保留一份确认无误的Gerber包作为参考。新项目导出后用脚本和参考包做对比差异一目了然。第三注意钻孔文件和Gerber的配合。钻孔文件Excellon格式通常单独导出它的文件名也可能骗人。校验时要把钻孔文件和Gerber的焊盘位置做比对确保钻孔落在焊盘中心。第四板厂反馈问题时先要他们的CAM报告。正规板厂在做CAM工程时会生成一份层分析报告里面会列出他们识别到的层类型。这份报告是校验你导出结果的最好参照。第五不要迷信自动校验。脚本能发现80%的问题但剩下的20%往往需要人的经验。比如某个层看起来特征都对但图形里有一个不该有的小孔这种问题脚本很难发现但人眼一看就知道不对劲。校验Gerber层这件事说到底是一个不信任文件名的思维习惯。一旦你养成了这个习惯很多低级错误就能在导出阶段被拦住省下的返工时间和打样费用远比写脚本的投入大得多。