3. PLC变量与数据类型
在Sysmac Studio中,变量是程序与硬件之间交换数据的唯一通道。与许多传统PLC用“地址”编程不同,Sysmac NJ/NX系列采用变量化编程:I/O、程序内部运算、HMI交互都通过具名变量完成,物理地址只在变量属性中映射。理解变量的作用域与数据类型,是后续编写可维护程序、实现PLC与HMI集成的第一步。
一、全局变量与局部变量:作用域决定可见性
Sysmac Studio把变量按作用域分为两类。全局变量定义在“全局变量表”中,整个工程的所有程序(POU)、功能块、HMI都能访问;局部变量定义在某个程序或功能块内部,只在该POU内可见。工程上的一条基本原则是:能用局部变量就不要用全局变量。局部变量随POU封装,修改时影响面小;全局变量一旦被多处引用,改名或改类型会牵动整个工程。
全局变量又细分为“变量”和“网络变量”两类。普通全局变量用于程序内部共享;网络变量(Network Variable)用于EtherNet/IP或EtherCAT网络上不同控制器之间的数据交换,需要指定发布/订阅关系。对于单机项目,通常只需普通全局变量。
局部变量在POU的变量声明区定义,分为内部变量(VAR)、输入变量(VAR_INPUT)、输出变量(VAR_OUTPUT)、输入输出变量(VAR_IN_OUT)和保持变量(VAR_RETAIN)。其中VAR_INPUT/VAR_OUTPUT/VAR_IN_OUT用于功能块与调用者之间的接口,是结构化编程的关键。
二、基本数据类型:选对类型才能省内存、防溢出
Sysmac Studio支持IEC 61131-3标准数据类型,常用的基本类型如下表。选择类型时既要考虑数值范围,也要考虑HMI和通信的兼容性。
| 类型 | 位宽 | 范围/说明 | 典型用途 |
|---|---|---|---|
| BOOL | 1位 | TRUE/FALSE | 按钮、限位、线圈 |
| BYTE/WORD/DWORD | 8/16/32位 | 无符号位串 | 状态字、掩码 |
| SINT/INT/DINT | 8/16/32位 | 有符号整数 | 计数、位置、温度×10 |
| USINT/UINT/UDINT | 8/16/32位 | 无符号整数 | 索引、长度 |
| REAL/LREAL | 32/64位 | 浮点数 | 模拟量、PID运算 |
| TIME | 64位 | 时间间隔 | 定时器设定值 |
| STRING | 可变 | 字符串 | 配方名、报警文本 |
工程上常见的错误是用INT存放模拟量。例如一个12位模拟量模块,原始值0~4095对应0~10V,若直接用INT存放原始值没问题;但若要做工程量转换,结果应使用REAL,否则小数部分会被截断。另一个常见问题是INT溢出:一个INT最大32767,若用INT做累计计数,超过就会翻转,应改用DINT或UDINT。
三、结构体、数组与枚举:组织复杂数据
结构体(STRUCT)把多个相关变量打包成一个数据类型。例如定义一个电机数据结构体:
TYPE ST_Motor :
STRUCT
bRun : BOOL; // 运行命令
bFault : BOOL; // 故障反馈
nSpeed : INT; // 转速设定
rCurrent : REAL; // 电流反馈
nStatus : WORD; // 状态字
END_STRUCT
END_TYPE
定义后即可声明stMotor1 : ST_Motor;,通过stMotor1.bRun访问成员。结构体让程序接口清晰,也便于HMI按结构批量绑定。
数组(ARRAY)用于存放同类型的多个元素,声明格式为aData : ARRAY[0..9] OF INT;。数组下标默认从0开始,也可指定为1..10。数组常用于配方、历史数据、多工位状态。注意数组越界在Sysmac中会触发异常,访问前应做下标范围判断。
枚举(ENUM)用有意义的名称代替数字,提高可读性。例如:
TYPE E_State :
(
eIdle := 0,
eRunning := 1,
ePause := 2,
eFault := 3
);
END_TYPE
声明eState : E_State;后,程序中可写eState := eRunning;,比写eState := 1;清晰得多。枚举在HMI中还能自动显示为文本列表。
四、工程化命名规范:让变量自己说话
变量名是程序可读性的第一道防线。Sysmac Studio允许中文变量名,但工程上建议使用英文或拼音首字母,避免编码问题。推荐一套可落地的命名规则:
- 作用域前缀:全局变量用
g_,局部输入用i_,局部输出用o_,输入输出用io_,保持变量用r_。 - 类型前缀:布尔
b,整数n,实数r,字符串s,结构体st,数组a,枚举e。 - 主体名:用驼峰式,如
bMotorRun、nSpeedSet、rTempValue。 - 单位后缀:带物理量时加单位,如
rTemp_C、nTime_ms,避免单位混淆。
例如一个全局的电机运行命令,命名为g_bMotor1Run;一个局部功能块的输出完成标志,命名为o_bDone。这样即使不看注释,也能大致判断变量的作用域、类型和用途。
五、实操示例:定义一个电机控制功能块的变量
假设要编写一个电机控制功能块FB_Motor,输入启动命令、速度设定,输出运行状态、故障。变量声明如下:
FUNCTION_BLOCK FB_Motor
VAR_INPUT
i_bStart : BOOL; // 启动命令
i_bStop : BOOL; // 停止命令
i_nSpeed : INT; // 速度设定,单位rpm,范围0~3000
END_VAR
VAR_OUTPUT
o_bRunning : BOOL; // 运行状态
o_bFault : BOOL; // 故障标志
o_nActual : INT; // 实际转速反馈
END_VAR
VAR
nState : E_State; // 内部状态枚举
tonStart : TON; // 启动延时定时器
END_VAR
VAR_RETAIN
nRunCount : DINT; // 累计运行次数,掉电保持
END_VAR
END_FUNCTION_BLOCK
调用时,在程序中声明一个实例fbMotor1 : FB_Motor;,然后写fbMotor1(i_bStart := g_bStart, i_nSpeed := 1500);。这样,功能块内部状态与外部隔离,只有输入输出接口暴露,符合高内聚低耦合的工程原则。
掌握变量作用域与数据类型后,下一步是把这些变量映射到实际I/O和HMI标签。在Sysmac Studio中,全局变量可以直接在“I/O映射”中绑定到EtherCAT从站或内置I/O,HMI则通过变量名直接引用,无需再关心物理地址。这正是变量化编程带来的集成便利。