FANUC 宏程序(Macro B)教程:变量分区怎么选、G65/G66/G67 怎么用、嵌套上限与 PS 报警对照

宏程序(Custom Macro B)是 FANUC 上最容易被”会用但不理解”的功能:变量声明不用写、类型不用管,但变量放错分区、拿 null 当 0 用、DO 与 END 不配对,出的故障都不报错或者报得莫名其妙。这篇按官方手册口径把变量分区、空值陷阱、调用方式、嵌套上限与 PS 报警一次讲清,最后一个能直接跑的法兰螺栓圆周钻孔实例。

相关阅读:宏程序实战(换刀宏 O9001 与 3202#4 NE9 解锁)见 FANUC 换刀宏程序(O9001)编写与恢复;报警号总表见 FANUC 基本 PS/BG/SR 报警代码大全。

一、变量分区:#1–#33 / #100–#199 / #500–#999 怎么选

选错分区是宏程序第一错。三区的生命周期完全不同:

表 1 三区变量对照(Macro B 官方口径)

分区范围断电后典型用途常见误用
局部变量#1 – #33调用结束即清G65/G66 传参(A=#1…Z=#26)、宏内部临时值拿它存工件计数——换一个调用就没了
公共变量(易失)#100 – #199清零单件加工内的临时计算、缓冲拿它存刀具寿命——断电归零,寿命统计全丢
公共变量(保持)#500 – #999保留工件计数、刀具寿命、原点偏置缓存、学习值拿它存每件都重算的中间值——挤占掉电要留的槽位

判断口诀:跟着”调用”走的放 #1–#33;断电必须还在的放 #500 段;其余临时计算放 #100 段。工件计数和刀具寿命放 #500–#999,这是新手最常错的地方——放 #100 段的计数器,一次断电就清零,操作工还以为闹鬼。

🚨 #500 段的上限随机型与参数不同:有的只有 #500–#599,有的到 #999,先在本机变量画面确认再规划。另外 #100–#199 是否断电清零也可能被参数改写,以本机手册为准。

FANUC Macro B 变量三区:#1-#33 局部变量随调用结束清空用于传参、#100-#199 公共变量断电清零存临时计算、#500-#999 保持型公共变量断电保留,工件计数与刀具寿命必须放 #500 段

二、空值 ≠ 0:#1 没传参时是 null

没赋值的变量是”空”(null),不是 0。这是宏程序里最坑的静默故障:

写法#1 为空时的行为#1 = 0 时的行为
G01 X#1 F300引用空的变量 → 该地址被忽略,轴不动、不报警正常走到 X0
#2 = #1 + 5空参与运算 → 结果按空处理#2 = 5
IF [#1 EQ 0] GOTO 10空与 0 比较按不相等处理条件成立

G01 X#1 在 #1 没赋值时不会报警、不会停、坐标就是不动——程序看起来在跑,件已经废了。排查办法:在变量画面里看该变量是空白(空)还是 0.000,空白就是没赋值。

两条纪律:

  1. 宏入口先把要用到的局部变量显式赋初值,别指望”它应该有值”;
  2. 判空用 [#1 NE #0](#0 永远是空),判零用 [#1 EQ 0]——两个判断别混用。

三、比较必须用运算符:EQ NE GT LT GE LE

广告

条件表达式里写 = 或 > 必然报错(格式错误类 PS 报警)。合法比较符只有六个:

运算符含义运算符含义
EQ等于(=)LT小于(<)
NE不等于(≠)GE大于等于(≥)
GT大于(>)LE小于等于(≤)

正确写法:IF [#101 GE 100] GOTO 20。写成 IF [#101 >= 100] 直接报表达式格式错。

四、逻辑组合:AND / OR / XOR 与方括号

  • 每个条件各自包一层方括号:IF [[#1 GT 0] AND [#2 LT 10]] GOTO 30;
  • AND / OR / XOR 是按位/逻辑运算符,写在中括号之间;
  • 括号本身也有限制:嵌套(含函数括号)最多 5 层,超了报 PS0118(TOO MANY NESTED BRACKETS,部分系列为 0118 段报警)。

五、IF-GOTO 与 IF-THEN

两种写法都能用,场景不同:

IF [#101 GT 100] GOTO 20        (条件成立跳到 N20,宏内跳转用 GOTO)
IF [#101 GT 100] THEN #102 = 1  (条件成立执行一条宏语句)
  • GOTO 只在同一个程序内跳,目标 N 号找不到报 PS0128(宏序列号不正确);
  • IF-THEN 后面只能跟一条宏语句,跟 NC 语句(如 G01)不行——要执行多句就跳转或子程序;
  • GOTO/WHILE 在 DNC 运行的主程序里不能用(相关报警 PS0123,视系列口径)。

六、WHILE / DO / END:最多 3 层、严格配对

#101 = 1
WHILE [#101 LE 10] DO1
    ...(循环体)
    #101 = #101 + 1
END1

表 2 DO/END 的硬性规则

规则内容违反后果
循环号DO1/END1 到 DO3/END3,只有 1–3PS0126 ILLEGAL LOOP NUMBER
配对每个 DO 必须有同号的 ENDPS0124 MISSING END STATEMENT(缺 END)
嵌套最多 3 层,且不能交叉(DO1…DO2…END1…END2 是交叉)报警或逻辑错乱
条件WHILE [条件] DO n,条件用第三章的六个比较符格式错

死循环自救:循环变量忘了自增是最常见的死机原因,循环体内第一件事就是改循环变量,或在循环体里放一个计数上限判断强制 GOTO 跳出。

七、调用方式:G65 / G66 / G66.1 / G67 / M98

表 3 五种调用方式对照

方式性质行为典型场景
G65 P_ L_非模态宏调用调一次、执行完返回,L=重复次数传参算一个孔位、算一个值
G66 P_模态宏调用每遇移动轴指令就调一次宏每个孔位都要执行的宏(配 G67 取消)
G66.1 P_模态宏调用(每块)每个程序块都调一次(不管有没有移动)每块都要刷新的高响应宏
G67取消模态调用取消 G66/G66.1用完必须取消,否则后续每个块都在调宏
M98 P_子程序调用无参数传递,固定重复不需要传参的固定动作

G66 的经典用法(钻孔宏):G81 打孔模式下挂 G66 宏,之后每个 X_ Y_ 块都自动进宏算一次,最后 G67 取消——忘 G67 是”后面程序全部行为异常”的经典原因。

G65 非模态调用一次即返回、G66 模态调用每个移动块都进宏、G66.1 每个程序块都进宏、G67 取消模态调用、M98 子程序无参数传递,G66 用完必须 G67

八、参数传递字母表:A=#1 … Z=#26 完整对照表

G65/G66 的自变量按字母 → 局部变量号固定映射(I/J/K 可重复传,按顺序依次入组):

表 4 自变量指定Ⅰ:字母 ↔ 局部变量号

字母变量字母变量字母变量
A#1I#4R#18
B#2J#5S#19
C#3K#6T#20
D#7M#13U#21
E#8Q#17V#22
F#9——W#23
H#11X#24Y#25
——Z#26——

不能用来自变量指定的地址:G、L、N、O、P(G 被系统占用——用了报 PS0129 非法参数地址;L 是重复次数、O 是程序号、N 是顺序号、P 是程序号/次数)。

同一字母只能传一个值;要传”一组同性质数据”(比如多个孔的坐标),用 I/J/K 重复指定(自变量指定Ⅱ,按 #4#5#6 一组一组往下排)。

九、嵌套上限与报错:PS0121 / PS0122 / PS0126

表 5 嵌套相关报警(官方报警信息原文口径)

报警信息含义处理
PS0121TOO MANY SUB, MACRO NESTING子程序 + 宏调用总数超上限(常见于外部存储器子程序调用期间又发起调用)缩短调用链、检查漏写的 M99
PS0122TOO MANY MACRO NESTING宏调用嵌套超上限(15i 手册明写上限 5 层;0i 系列常见口径为宏调用 4 层)减少宏套宏的层数
PS0124MISSING END STATEMENT有 DO 没 END(DO-END 必须 1:1 配对)补 END;注意不是”交叉嵌套”那个错
PS0126ILLEGAL LOOP NUMBERDO/END 号不在 1–3改成 DO1–DO3
广告

🚨 层级口径随系列略有差异:15i 手册写宏嵌套 5 层,0i 系列手册常见”宏调用 4 层”,”子程序 15 层”是流传很广的资料口径、未在本次核实的原文中出现——以你手上这台上电后手册(参数说明)为准。

十、PS 报警速查:宏程序高频报警对照

表 6 写宏最容易撞上的 PS 报警

报警信息触发原因处理
PS0112ZERO DIVIDE除数为 0(#1/#0 或变量为 0 的除法)除之前判 [#2 NE 0]
PS0114ILLEGAL EXPRESSION FORMAT表达式格式错(括号/运算符)检查方括号配对与运算符写法
PS0115VARIABLE NO. OUT OF RANGE变量号越界(如 #9999、超本机上限)先确认本机 #500 段到几
PS0116WRITE PROTECTED VARIABLE给只读变量赋值(多数系统变量)只读别写
PS0118TOO MANY NESTED BRACKETS括号嵌套超 5 层(含函数括号)拆表达式
PS0122TOO MANY MACRO NESTING宏调用嵌套超上限减层数
PS0124MISSING END STATEMENTDO 无对应 END补 END
PS0126ILLEGAL LOOP NUMBERDO/END 号不在 1–3用 DO1–DO3
PS0127NC, MACRO STATEMENT IN SAME BLOCKNC 指令与宏语句写在同一块(如 G01 X#1 #2=5)宏语句单独一行
PS0128ILLEGAL MACRO SEQUENCE NUMBERGOTO/M99P 的目标 N 号找不到核对 N 号与范围
PS0129ILLEGAL ARGUMENT ADDRESS用了不允许的自变量地址(如 G)换合法字母
FANUC 宏程序高频 PS 报警速查:PS0112 除零、PS0114 表达式格式、PS0115 变量号越界、PS0116 写保护、PS0118 括号嵌套、PS0122 宏嵌套超限、PS0124 缺 END、PS0126 DO 号越界、PS0127 NC 与宏同块、PS0128 跳转号找不到、PS0129 非法自变量地址

十一、数学与函数:FIX / FUP / ROUND,角度一律用度

函数含义注意
FIX[ ]向绝对值小的方向舍去小数FIX[1.7]=1,FIX[−1.7]=−1
FUP[ ]向绝对值大的方向进位FUP[1.3]=2,FUP[−1.3]=−2
ROUND[ ]四舍五入(在表达式内是”四舍五入到整数”)用在移动指令地址上时行为不同(按最小设定单位圆整)——表达式内与地址上别混用
SQRT / ABS平方根 / 绝对值—
SIN / COS / TAN三角函数角度一律是度,没有 RAD 关键字:SIN[30]=0.5
ATAN反正切(格式 ATAN[y]/[x],部分系列带斜杠)返回值也是度
LN / EXP自然对数 / e 的幂—

两个易错点:

  1. 整数除法截断:#1 = 7 / 2 得 3(截断不四舍五入);要小数结果,先乘 1.0 或用浮点形式 #1 = 7.0 / 2;
  2. 三角函数用度——把 CAD 图上的弧度抄进 SIN/COS 是最常见的”宏算出来的坐标全偏”原因。

十二、可运行实例:法兰螺栓圆周均布钻孔

需求:法兰中心 (X0 Y0),分布圆半径 R(#18),孔数 N(#20),起始角 A(#1,度),孔深 Z(#26),钻速 F(#9)。宏 O9010:

O9010 (BOLT CIRCLE DRILL)
#101 = 0                      (计数, 临时变量放 #100 段)
WHILE [#101 LT #20] DO1
  #102 = #1 + #101 * 360.0 / #20        (当前孔角度=度)
  #103 = #18 * COS[#102]                (X = R*cos)
  #104 = #18 * SIN[#102]                (Y = R*sin)
  G00 X#103 Y#104
  G00 Z#105                             (安全面, 由主程序传入或固定值)
  G01 Z#26 F#9
  G00 Z5.0
  #101 = #101 + 1
END1
M99
法兰螺栓圆周均布钻孔宏 O9010:传参 R60.进 #18、A30.进 #1 起始角、T8 进 #20 孔数,宏内 #101-#104 都用 #100 段,WHILE 循环逐孔算角度后 COS/SIN 定位钻孔,角度一律用度

主程序调用:G65 P9010 R60. A30. Z-15. F120. T8(R=分布半径 60,A=起始角 30°,8 孔)。角度是度(COS[30]=0.866),循环变量用 #100 段(不用保存),孔数与半径经字母表进 #20/#18。

改造练习:把”计数 + 逐孔算角度”改成 G66 模态版(每块进宏),体会 G67 忘写的后果;再把加工件数累计写到 #500 段做产量统计——正好覆盖第一、七章的两个要点。

常见问题

FANUC 宏程序里 #100 和 #500 有什么区别?哪个断电不丢?

#500 断电不丢。#1–#33 是局部变量,跟着 G65/G66 调用走,调用返回就清掉,只用来传参和存宏内临时值;#100–#199 是易失公共变量,断电清零,适合单件加工内的临时计算;#500–#999 是保持型公共变量,断电保留,工件计数、刀具寿命、原点缓存这类必须跨电源周期的值都放这里。把计数器放 #100 段是新手最常犯的错——一次断电统计全丢。注意 #500 段的上限随机型不同(有的只到 #599),先在变量画面确认本机范围再规划。

宏程序调用报警 PS0124 是怎么回事?

PS0124 是 MISSING END STATEMENT:程序里有一个 DO 却找不到与它配对的 END。Macro B 的 DO/END 必须同号 1:1 配对(DO1 对 END1),循环号只能在 1–3 之间(越界是另一个报警 PS0126),嵌套最多 3 层且不能交叉(DO1…DO2…END1…END2 就是交叉)。处理办法是从头数 DO/END:每个 DO 往下找同号 END,缺的补上;多层嵌套时建议在 END 后面加注释标明配对关系。如果 DO/END 数量看着是配对的还报 0124,检查是不是把 END 写在了 IF 分支里导致扫描路径上不闭合。

宏程序里的角度是弧度还是度?正弦函数怎么写?

一律是度,Macro B 没有 RAD 关键字。SIN[30] 就是 sin 30° = 0.5。常用写法:#101 = #18 * COS[#102]、#102 = #1 + #101 * 360.0 / #20(把孔序号换算成角度时直接用 360.0,不用做任何弧度换算)。与之相对,FANUC 的极坐标 G112/G12.1 或某些 CAM 后置里的三角计算可能用别的单位——跨系统抄公式时先确认单位。另外两个算术坑:整数除法会截断(7/2=3,要小数写成 7.0/2);ROUND 在表达式内是四舍五入到整数、用在移动地址上是按最小设定单位圆整,两者别混用。

最后更新:2026-10-25

本文有英文版:Fanuc Macro B Guide: Variable Partitions, G65/G66/G67 Calls, Nesting Limits and PS Alarm Codes
面向海外读者的完整英文版,内容与本文对应 — 可直接转给非中文同事或海外客户。
© 版权声明
THE END
喜欢就支持一下吧
点赞5赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容

广告