流程控制编程

流程控制编程指南,讲解程序流程控制、输入输出、条件跳转与子程序调用等编程方法,帮助快速构建机械手作业流程。

最近更新 2026-08-13 全文字数 5,953 35 个章节

文档编写:博飞宇智能科技
版本:V1.1

目录#

重要限制#

流程控制语句(IF / WHILE / SUB 等)仅在从文件系统加载的宏程序中可用,不能在交互模式下直接输入使用。

宏文件需放置在文件系统中,通常路径为:

  • /littlefs/<name>.ngc(LittleFS 文件系统)
  • /<name>.ngc(SD 卡根目录)

1. 表达式语法#

1.1 运算符#

算术运算符#

运算符 说明 示例
+ 加法 [3 + 5] = 8
- 减法 [10 - 3] = 7
* 乘法 [4 * 3] = 12
/ 除法 [10 / 3] = 3.333
MOD 取模 [10 MOD 3] = 1
** 幂运算 [2 ** 3] = 8

关系运算符(返回 1.0 为真,0.0 为假)#

运算符 说明 示例
LT 小于 [3 LT 5] = 1.0
LE 小于等于 [5 LE 5] = 1.0
EQ 等于 [3 EQ 3] = 1.0
NE 不等于 [3 NE 5] = 1.0
GE 大于等于 [5 GE 3] = 1.0
GT 大于 [5 GT 3] = 1.0

逻辑运算符#

运算符 说明 示例
AND 按位与 [5 AND 3] = 1
OR 按位或 [5 OR 3] = 7
XOR 按位异或 [5 XOR 3] = 6

1.2 数学函数#

函数 说明 示例
ABS[x] 绝对值 ABS[-5] = 5
ACOS[x] 反余弦(弧度) ACOS[1] = 0
ASIN[x] 反正弦(弧度) ASIN[1] = 1.5708
ATAN[x]/[y] 反正切(弧度) ATAN[1]/[1] = 0.7854
COS[x] 余弦(弧度) COS[0] = 1
SIN[x] 正弦(弧度) SIN[1.5708] = 1
TAN[x] 正切(弧度) TAN[0.7854] = 1
SQRT[x] 平方根 SQRT[16] = 4
EXP[x] e 的 x 次方 EXP[1] = 2.718
LN[x] 自然对数 LN[2.718] = 1
ROUND[x] 四舍五入 ROUND[3.6] = 4
FIX[x] 向零取整 FIX[-3.6] = -3
FUP[x] 远离零取整 FUP[-3.2] = -4
EXISTS[#<name>] 参数是否存在 EXISTS[#<_x>] = 1
PRM[x] 读取设置值 PRM[100] 读取 $100 设置

2. 参数(变量)#

2.1 编号参数#

范围 说明 持久性
#1 ~ #30 子程序局部参数,CALL 时传递 调用级局部
#31 ~ #5000 全局参数 断电保持
#5001 ~ #5399 全局参数 断电不保持

使用方式#

#100 = 50.0          (设置编号参数)
G0 X#100             (引用编号参数)
#101 = [#100 + 10]   (表达式中使用编号参数)

2.2 系统变量(只读,以 _ 开头)#

参数 说明
_x _y _z _a _b _c 当前相对坐标
_abs_x _abs_y _abs_z ... 当前绝对坐标
_feed 当前进给速率
_input0 ~ _input5 输入信号状态
_motion_mode 当前运动模式
_plane 当前平面选择
_absolute 是否绝对坐标模式
_homed_state 回零状态
_call_level 当前调用层级
_value 子程序返回值
_value_returned 子程序是否返回了值
_free_memory 剩余内存
_line 当前行号

使用方式#

#<pos_x> = #<_abs_x>    (读取当前绝对 X 坐标到自定义参数)

#1 = #_input0
O100 IF [#1 EQ 1]
    (输入 0 为高电平,执行某操作)
O100 ENDIF

O200 (等待输入 1 变高)
WHILE [#_input1 EQ 0]
    G4 P0.1
ENDWHILE

3. 流程控制语句#

所有流程控制语句使用 O 代码格式,语法遵循 LinuxCNC O 代码规范。

O 标签可以是数字字符串

  • 数字标签:O100 IF [...]O200 WHILE [...]
  • 字符串标签:O<myloop> WHILE [...]O<mysub> SUB

3.1 条件判断 IF / ELSEIF / ELSE / ENDIF#

基本用法#

(文件: /littlefs/test_if.macro)

#1 = 10
O100 IF [#1 GT 5]
    G0 X50 Y50       (当 #1 > 5 时执行)
O100 ENDIF

IF-ELSE 结构#

#1 = 3
O100 IF [#1 GT 5]
    G0 X100          (#1 > 5 时执行)
O100 ELSE
    G0 X0            (#1 <= 5 时执行)
O100 ENDIF

IF-ELSEIF-ELSE 链式判断#

#1 = 5
O100 IF [#1 EQ 1]
    G0 X10
O100 ELSEIF [#1 EQ 5]
    G0 X50           (#1 == 5 时执行此处)
O100 ELSEIF [#1 EQ 10]
    G0 X100
O100 ELSE
    G0 X0            (以上条件都不满足时执行)
O100 ENDIF

嵌套 IF#

#1 = 10
#2 = 20
O100 IF [#1 GT 5]
    O200 IF [#2 GT 15]
        G0 X100 Y100    (两个条件都满足时执行)
    O200 ELSE
        G0 X100 Y0
    O200 ENDIF
O100 ELSE
    G0 X0 Y0
O100 ENDIF

3.2 WHILE 循环#

基本用法#

(计算 1+2+...+10)
#1 = 0          (累加结果)
#2 = 1          (计数器)
O100 WHILE [#2 LE 10]
    #1 = [#1 + #2]
    #2 = [#2 + 1]
O100 ENDWHILE
(此时 #1 = 55)
G0 X#1

使用 BREAK 跳出循环#

(查找第一个满足条件的位置)
#1 = 0
O100 WHILE [#1 LE 100]
    #1 = [#1 + 1]
    O200 IF [#1 ** 2 GT 50]
        O100 BREAK     (跳出 O100 循环)
    O200 ENDIF
O100 ENDWHILE
(此时 #1 = 8,因为 8^2 = 64 > 50)

使用 CONTINUE 跳过本次迭代#

(累加 1-10 中的奇数)
#1 = 0          (累加结果)
#2 = 0          (计数器)
O100 WHILE [#2 LT 10]
    #2 = [#2 + 1]
    O200 IF [#2 MOD 2 EQ 0]
        O100 CONTINUE   (偶数跳过)
    O200 ENDIF
    #1 = [#1 + #2]
O100 ENDWHILE
(此时 #1 = 25 = 1+3+5+7+9)

3.3 DO-WHILE 循环#

先执行循环体,后判断条件(至少执行一次):

(至少执行一次,直到 #1 >= 10)
#1 = 0
O100 DO
    G0 X#1
    #1 = [#1 + 2]
O100 WHILE [#1 LT 10]
(依次移动到 X0, X2, X4, X6, X8)

3.4 REPEAT 循环#

固定次数重复执行:

(重复钻孔 5 次,每次间距 10mm)
#1 = 0
O100 REPEAT [5]
    G0 X#1
    G1 Z-5 F100
    G0 Z5
    #1 = [#1 + 10]
O100 ENDREPEAT

3.5 子程序 SUB / CALL#

定义和调用子程序(数字标签)#

(文件: /littlefs/drill_pattern.macro)

(定义子程序:在当前位置钻孔)
O100 SUB
    G1 Z-5 F100      (下钻)
    G0 Z5             (抬刀)
O100 ENDSUB

(主程序:在 5 个位置调用子程序)
#1 = 0
O200 REPEAT [5]
    G0 X#1 Y0
    O100 CALL          (调用子程序 O100)
    #1 = [#1 + 10]
O200 ENDREPEAT

子程序传参(位置参数 #1 - #30)#

(文件: /littlefs/drill_at.macro)

(定义带参数的子程序:在指定位置钻孔)
O100 SUB
    G0 X#1 Y#2        (移动到 #1=X, #2=Y 指定的位置)
    G1 Z#3 F100       (下钻深度由 #3 指定)
    G0 Z5
O100 ENDSUB

(主程序:在不同位置和深度钻孔)
O100 CALL [10] [20] [-5]     (在 X10 Y20 钻深 5)
O100 CALL [30] [40] [-8]     (在 X30 Y40 钻深 8)
O100 CALL [50] [10] [-3]     (在 X50 Y10 钻深 3)

子程序返回值#

(文件: /littlefs/calc_area.macro)

(定义计算面积的子程序)
O100 SUB
    #10 = [#1 * #2]     (长 * 宽)
O100 ENDSUB [#10]       (返回面积值)

(主程序)
O100 CALL [5] [3]       (计算 5x3 的面积)
#<area> = #<_value>     (读取返回值到命名参数)
(此时 #<area> = 15.0,#<_value_returned> = 1.0)

命名子程序(从 .ngc 文件加载)#

命名子程序以字符串标签标识,系统会自动从文件系统加载对应的 .ngc 文件。

(文件: /littlefs/drill_slot.ngc)

(调用命名子程序,系统自动加载 /littlefs/safe_drill.ngc)
O<safe_drill> CALL [50] [30] [-10]

对应的子程序文件 /littlefs/safe_drill.ngc

(安全钻孔子程序)
(参数: #1=X, #2=Y, #3=深度)
G0 Z5                  (先抬刀到安全高度)
G0 X#1 Y#2             (快速移动到目标位置)
G1 Z#3 F80             (慢速下钻)
G0 Z5                  (抬刀返回安全高度)

3.6 RETURN 语句#

从子程序中提前返回:

O100 SUB
    O200 IF [#1 LT 0]
        O100 RETURN     (参数无效,提前返回)
    O200 ENDIF
    G0 X#1
O100 ENDSUB

3.7 触发报警或错误#

(参数越界时触发报警)
O100 IF [#1 LT 0]
    O100 ALARM [1]      (触发报警码 1)
O100 ENDIF

(严重错误时触发错误码)
O200 IF [#2 EQ 0]
    O200 ERROR [80]     (触发错误码 80)
O200 ENDIF

3.8 读取机器状态#

G65 P4                    (获取机器状态)
#<state> = #<_value>      (读取返回值)

(状态值: 0=空闲, 1=报警, 2=检查模式, 3=回零中, 4=运行中, 5=暂停, 6=点动, 7=未知, 8=休眠, 9=急停)
O100 IF [#<state> EQ 4.0]
    MSG,机器正在运行中
O100 ELSEIF [#<state> EQ 9.0]
    O100 ALARM [1]        (急停状态,触发报警)
O100 ELSEIF [#<state> EQ 0.0]
    MSG,机器空闲
O100 ENDIF

3.9 检查轴是否回零#

(检查 Z 轴是否已回零,Z_AXIS = 4)
#<homed_mask> = #<_homed_axes>
#<z_homed> = [#<homed_mask> AND 4]

O100 IF [#<z_homed> EQ 4.0]
    G0 Z5               (Z 轴已回零)
O100 ELSE
    O100 ALARM [9]       (Z 轴未回零,报警)
O100 ENDIF

4. 注意事项#

  1. 文件系统依赖:流程控制语句必须从文件系统(LittleFS 或 SD 卡)加载的 .ngc 文件中执行,串口或网口直接输入不支持。

  2. 栈深度限制:嵌套层级最大为 20 层,包括嵌套的 IF、WHILE、CALL 等。超出会触发 Status_FlowControlStackOverflow 错误。

  3. 参数数量限制:CALL 传递的位置参数最多 30 个(#1 ~ #30)。

  4. 内存限制:WHILE 循环的表达式需要动态分配内存保存,子程序信息也需要 malloc。内存不足时会触发 Status_FlowControlOutOfMemory 错误。

  5. O 标签匹配:每个流程控制块的开始和结束必须使用相同的 O 标签,例如 O100 IF 必须对应 O100 ENDIF,否则会报语法错误。

  6. 表达式中的方括号:表达式必须用 [] 包裹,如 [3 + 5],不支持 ()。嵌套表达式也用 [],如 [[3 + 5] * 2]

  7. 浮点比较:条件判断中 EQ(等于)对浮点数可能不精确,建议使用范围判断,如 [ABS[#1 - #2] LT 0.001] 代替 [#1 EQ #2]

  8. 注释中的 ABORT:在注释中使用 (ABORT,消息内容) 可以在流程控制中触发用户异常,中断执行并显示消息。


文档编写:博飞宇智能科技
版本:V1.1