搜索文章与案例

Technical Article

海德汉 QL 参数为什么被改了?CALL LBL 与 CALL PGM 的作用域

海德汉TNC 640的QL局部参数,为什么CALL LBL返回后变成25,CALL PGM返回后仍为20?按34059x-18手册,用两张数据流图核对NC程序范围、Q1600显式输出及坐标变换边界。

把一段计算从主程序里的 LBL 抽成独立的 CALC.H,调用方式改成 CALL PGM 后,计算段里明明已经得到 25,主程序接着读 QL1,却还是 20。反过来,原本想把 QL1 当成子程序的临时量,执行 CALL LBL 后,主程序里的值又跟着变了。遇到这种现象,先查这次调用有没有进入另一个 NC 程序。

海德汉 QL 的“局部”,以当前 NC 程序为范围。本文按 TNC 640、NC 软件 34059x-18、2023 年 10 月版官方 Klartext 手册说明,讨论普通 CALL LBL 和 CALL PGM;示例不使用 FN 37 EXPORT、OEM 宏或专用循环。下面给出的数值是按手册规则推演的结果,计算只涉及变量。

同一程序里的 LBL,共用这一份 QL1

官方手册把 QL0~QL499 定义为在一个 NC 程序内局部有效的用户参数。同时,CALL LBL 的执行顺序是进入本程序中的标签段,执行到 LBL 0,再回到调用后的下一段。结合这两处定义可知:一个 LBL 标签不会另外划出一套独立的 QL 参数。

设 MAIN_A.H 在调用前把 QL1 设为 20,调用结束后用 QL2 记录它的值。这里只摘出相关调用和赋值行:

FN 0: QL1 = +20
CALL LBL 10
FN 0: QL2 = +QL1

同一 MAIN_A.H 中的 LBL 10 做一次加法:

LBL 10
FN 1: QL1 = +QL1 + +5
LBL 0

QL1 的演算是 20+5=25。返回后,主程序读到的仍是本程序这份 QL1,因此 QL2 得到 25。改变数值的是 LBL 内执行的加法,CALL LBL 本身没有自动加数或清零的作用。

这些摘录不能直接首尾拼接。按手册的普通子程序结构,LBL 子程序应放在主程序 M2 或 M30 之后,避免主流程顺序落入标签段。本文的 CALL LBL 10 不带 REP;CALL LBL REP 的程序块重复次数是另一种执行结构,不能混在这里计算。

换成独立 CALC.H,同号 QL1 各在各的程序里

另一组示例从头开始。MAIN_B.H 把自己的 QL1 设为 20,再调用同目录的 CALC.H:

FN 0: QL1 = +20
CALL PGM CALC
FN 0: QL2 = +QL1

CALC.H 也显式初始化自己的 QL1,然后加 5。这样不需要猜测进入被调程序时局部参数的初值:

0 BEGIN PGM CALC MM
1 FN 0: QL1 = +20
2 FN 1: QL1 = +QL1 + +5
3 END PGM CALC MM

CALC.H 内的 QL1 得到 25;普通 CALL PGM 返回后,MAIN_B.H 里的 QL1 仍为 20,接下来的 QL2 也得到 20。官方在外部程序调用章节明确建议使用仅在当前 NC 程序生效的 QL,避免被调程序的参数修改影响调用方。

QL参数作用域对照。MAIN_A.H内CALL LBL 10使同一份QL1由20加5得到25,返回后QL2为25。MAIN_B.H通过CALL PGM调用CALC.H,后者自己的QL1由20变25,返回后MAIN_B.H的QL1和QL2仍为20。
图 1 框表示当前 NC 程序的局部范围。左右是分别开始的两组演算,箭头表示调用顺序,不表示轴运动。

这里能确定的是本次调用的参数范围,不能据此推导 QL 在重选程序、复位或断电后还保留什么。要比较两种调用,像上面一样,在每组起点和每个被调程序中明确赋初值,记录调用前、计算后及返回后的值。

要把 25 交回主程序,就约定一个输出参数

如果 CALC.H 的任务就是算出一个值交给主程序,单纯改它自己的 QL1 不够。可以为这个普通 CALL PGM 调用约定一个共享的 Q 参数作为输出。以下选 Q1600:该号位于本版手册的用户参数范围内,但接入实际项目之前,仍要查清它是否已经被别的程序使用。

主程序调用前将 Q1600 显式设为 0;CALC.H 算出 25 后、到达 END PGM 之前,增加这一行:

FN 0: Q1600 = +QL1

返回后,主程序从约定输出位取值:

FN 0: QL2 = +Q1600

这时 MAIN_B.H 的 QL1 仍为 20,QL2 则得到 25,Q1600 也是 25。输出关系由赋值行写清楚,不需要依赖两个程序恰好用了相同的 QL 号码。

普通CALL PGM的显式输出流程:MAIN_B.H先令QL1为20、Q1600为0;CALC.H将自己的QL1算成25并赋给Q1600;返回后MAIN_B.H从Q1600读取到QL2,因此QL1保持20、QL2和Q1600为25。
图 2 Q1600 是本例约定的输出位置。显式初始化用来排除上次残值;实际流程还应确认输出赋值所在分支确实执行过。

把输出位清成 0,只能消除旧值,不能证明本次计算成功。若实际程序有条件跳过计算、提前返回或多个结果分支,还需另外约定完成标志及其检查位置,不能把“读到了一个数”当成结果已更新。

整理后处理时,先画调用关系再分配参数

把 LBL 拆成独立程序,或者把外部程序重新合并进主程序,都会改变 QL 的可见范围。检查这种修改时,不能只比较计算公式是否一字未动,还要记录每一份 QL 属于哪个 NC 程序、输入从哪里来、输出写到哪里去。

同一主程序里两个 LBL 都拿 QL1 当临时量,后执行的标签段就可能覆盖前一段留下的值。若前一个结果还要继续用,应调整参数分配,或在覆盖前保存到本程序内约定且未占用的位置。把 Q 全部替换成 QL,也可能切断原来有意共享的输入和输出。

本文用 Q1600 说明普通外部调用的共享输出,不把规则扩大为“所有 Q 在任何地方都全局”。手册还列有 Q0~Q99 在宏与循环内的局部例外。遇到 OEM 宏或专用循环,应按它自己的参数接口核对。修改前后可对照后处理 NC 输出比较方法,把调用方式和参数赋值行放在一起审查。

QL 隔离了变量,并不替你恢复坐标变换

CALC.H 使用自己的 QL,不代表它对加工状态也完全隔离。官方外部程序调用章节特别提示:被调程序中使用而未复原的坐标变换,可能继续影响调用方。因此,确认“主程序的 QL1 没变”之后,还要单独检查被调程序有没有留下零点偏移、旋转等状态。

从实际程序里缩小问题时,可以先保留本文这种不含轴运动的赋值与调用,在对应 34059x-18 编程站中核对三处参数:调用前的 QL1、被调段计算后的 QL1、返回后记录的 QL2。随后再逐项核对原程序的输入输出与状态恢复。这样,QL 取值问题和运动状态问题都有明确的检查位置,不会把“局部参数”误当成整个调用的自动复原开关。

参考资料

海德汉《TNC 640 Klartext 对话式编程用户手册》,892903-ZB,NC 34059x-18,10/2023。第 223 页为 CALL LBL 与 LBL 0 的调用结构;第 225~227 页为外部 NC 程序调用、QL 使用提示、路径及坐标变换提醒;第 241 页为参数类型和范围,第 245~246 页为赋值及加法。文中调用前后的数值和两张图,是依据这些规则编制的原创演算。

英文同版 892903-2C 的对应位置为第 253、258~260、277、283 页。本文“同一程序的 LBL 共用该程序的 QL”由局部范围定义与 CALL LBL 结构结合推得。