跳到主要内容

变量与数据类型

Darra PLC 变量系统遵循 IEC 61131-3 标准,提供类型安全的变量声明、多级作用域和丰富的数据类型。变量表由 PLCVariableTable 管理,支持符号名到内存地址的双向映射。

变量声明

声明语法

VAR                          // 局部变量
iCount : INT := 0;
rSpeed : REAL;
bReady : BOOL := FALSE;
END_VAR

VAR_INPUT // 输入参数 (功能块)
bEnable : BOOL;
END_VAR

VAR_OUTPUT // 输出参数 (功能块)
bDone : BOOL;
END_VAR

VAR_IN_OUT // 输入输出参数 (引用传递)
arBuffer : ARRAY[0..99] OF INT;
END_VAR

VAR_GLOBAL // 全局变量
giBatchCount : INT;
grTemperature : REAL;
END_VAR

VAR RETAIN // 掉电保持变量
riTotalParts : INT;
rrCalibOffset : REAL;
END_VAR

VAR CONSTANT // 常量
MAX_SPEED : REAL := 6000.0;
TIMEOUT : TIME := T#30s;
END_VAR

作用域

作用域关键字可见范围生命周期
局部VAR当前 POU 内部每次调用重新初始化
全局VAR_GLOBAL所有 POU程序运行期间
保持VAR RETAIN声明所在 POU跨停止/启动保持
常量VAR CONSTANT声明所在 POU编译时确定
Retain 变量

Retain 变量在 PLC 停止、重新启动后保持上次运行的值。适用于产量计数、累计运行时间、标定参数等。冷启动 (OB100) 时可选择是否重置 Retain 变量。

基本数据类型

位类型

类型大小范围用途
BOOL1 位TRUE / FALSE开关量
BYTE8 位0 ~ 255位掩码
WORD16 位0 ~ 65535状态字
DWORD32 位0 ~ 2^32-1控制字
LWORD64 位0 ~ 2^64-1时间戳

整数类型

类型大小有符号范围
SINT8 位-128 ~ 127
USINT8 位0 ~ 255
INT16 位-32768 ~ 32767
UINT16 位0 ~ 65535
DINT32 位±2.1×10^9
UDINT32 位0 ~ 4.2×10^9
LINT64 位±9.2×10^18
ULINT64 位0 ~ 1.8×10^19

浮点类型

类型大小精度用途
REAL32 位~7 位有效数字一般模拟量
LREAL64 位~15 位有效数字高精度运算 (角度/位置)

时间与字符串

类型格式示例
TIMET#<值>T#1s, T#500ms, T#2h30m
DATED#<日期>D#2026-04-07
TODTOD#<时间>TOD#14:30:00
DTDT#<日期时间>DT#2026-04-07-14:30:00
STRING单引号'Hello', 最长 255 字符
WSTRING双字节Unicode 字符串

数组

VAR
// 一维数组
aiSensors : ARRAY[0..7] OF INT;

// 多维数组
arGrid : ARRAY[0..3, 0..3] OF REAL;

// 初始化
aiPreset : ARRAY[0..4] OF INT := [10, 20, 30, 40, 50];
END_VAR

// 访问
aiSensors[3] := 100;
arGrid[1, 2] := 3.14;

结构体

TYPE ST_MotorStatus :
STRUCT
bOnline : BOOL;
bFault : BOOL;
iErrorCode : INT;
rActualSpeed : REAL;
rActualPos : LREAL;
tRunTime : TIME;
END_STRUCT;
END_TYPE

VAR
stMotor1 : ST_MotorStatus;
astMotors : ARRAY[0..5] OF ST_MotorStatus;
END_VAR

// 访问
stMotor1.rActualSpeed := 1500.0;
astMotors[2].bFault := TRUE;

枚举

TYPE E_MachineState :
(
IDLE := 0,
HOMING := 1,
RUNNING := 2,
PAUSED := 3,
STOPPING := 4,
ERROR := 99
);
END_TYPE

VAR
eState : E_MachineState := E_MachineState.IDLE;
END_VAR

IF eState = E_MachineState.RUNNING THEN
// ...
END_IF;

类型转换

// 显式类型转换函数
rValue := INT_TO_REAL(iCount);
iValue := REAL_TO_INT(rTemp); // 四舍五入
diValue := INT_TO_DINT(iSmall);
sValue := INT_TO_STRING(iCount);
tValue := DINT_TO_TIME(diMs); // 毫秒转 TIME
类型安全

Darra PLC 编译器强制类型检查。不同类型之间赋值必须使用显式转换函数,隐式转换将报编译错误。这避免了因精度丢失或溢出导致的运行时故障。

变量作用域完整列表

IEC 61131-3 完整作用域关键字:

FUNCTION_BLOCK FB_Example
VAR_INPUT // 输入参数, 按值传递 (简单类型) 或按引用 (复杂类型)
bStart : BOOL;
rSpeed : REAL;
END_VAR

VAR_OUTPUT // 输出参数
bDone : BOOL;
rActual : REAL;
END_VAR

VAR_IN_OUT // 输入输出, 总是按引用传递, 修改直接影响调用方
stContext : ST_Context;
END_VAR

VAR // FB 实例持有的内部状态, 实例间独立
tonDelay : TON;
iState : INT;
END_VAR

VAR_TEMP // 临时变量, 每次调用重新初始化 (栈分配)
iLocal : INT;
END_VAR

VAR_STAT // 静态变量, 同一 FB 所有实例共享 (类级共享)
iGlobalCounter : INT;
END_VAR

VAR_INST // 实例内存变量 (=VAR, 在 FUNCTION 里等价)
iRetry : INT;
END_VAR

VAR CONSTANT // 常量, 编译时确定, 不可修改
MAX_SPEED : REAL := 6000.0;
TIMEOUT : TIME := T#30s;
END_VAR

VAR RETAIN // 断电保持, 掉电后 PV 保留
riTotalParts : DINT;
END_VAR

VAR PERSISTENT // 持久化 (比 RETAIN 更强, 冷启动也不清零)
riCalibOffset : LREAL;
END_VAR

END_FUNCTION_BLOCK

作用域详细对比

关键字作用域生命周期初始化时机典型用途
VAR_INPUTPOU 内只读调用期间每次调用赋值函数参数
VAR_OUTPUTPOU 内可写跨调用保持 (FB)初次调用初始化返回结果
VAR_IN_OUTPOU 内可写引用调用方永不复制大数据结构传递
VARPOU 内部FB 实例生命周期实例创建时内部状态
VAR_TEMPPOU 内部单次调用每次调用重置局部临时
VAR_STATPOU 内部程序运行期首次访问类级计数
VAR_GLOBAL全项目程序运行期OB100 初始化全局共享
VAR CONSTANT声明处编译时编译期求值魔数替代
VAR RETAIN声明处断电保持冷启动可选清零产量累计
VAR PERSISTENT声明处永久保持仅手动清零标定参数
VAR_IN_OUT 零拷贝

VAR_IN_OUT引用传参, 适合传递大数组或结构体。相比 VAR_INPUT (值传递) 零开销, 但修改会反映到调用方。需要注意所有权。

RETAIN 与 PERSISTENT

两者都是断电保持, 但清零策略不同:

特性VAR RETAINVAR PERSISTENT
热重启保持
冷启动保持可配置 (默认清零)✓ 始终保持
下载新程序保持
手动复位命令可清零仅专用命令
物理存储非易失内存 (NVRAM)非易失内存 (NVRAM) + 备份
典型用途产量 / 运行小时标定系数 / 工具 TCP / 零点偏移
何时用哪个
  • 产量计数, 累计运行时: 每次开机可清零 → VAR RETAIN
  • 机械标定, 软限位, 螺距补偿: 下载新程序也不能丢 → VAR PERSISTENT
  • HMI 临时数据: 不需要掉电保持 → 普通 VAR

初始值

所有变量都可以指定初始值:

VAR
// 简单类型初始化
bReady : BOOL := FALSE;
iCount : INT := 100;
rSpeed : REAL := 1500.0;

// 字符串初始化
sName : STRING[32] := 'Darra PLC';

// 数组初始化
aiPreset : ARRAY[0..4] OF INT := [10, 20, 30, 40, 50];
arZeros : ARRAY[0..99] OF REAL := [100(0.0)]; // 100 个 0.0

// 结构体初始化
stMotor : ST_Motor := (sName := 'M1', iId := 1, rMaxSpeed := 3000.0);

// 枚举初始化
eState : E_State := E_State.IDLE;

// 时间初始化
tDelay : TIME := T#500ms;
dToday : DATE := D#2026-04-18;
END_VAR
初始值执行时机
  • 冷启动 (OB100): 所有变量重置为初始值
  • 热重启: RETAIN / PERSISTENT 保持上次值, 其他重置
  • 在线重新下载: 由用户选择"保留数据"或"清零"

地址映射 (AT 语句)

AT 显式绑定变量到内存地址:

VAR
// I 区 — 物理输入
bStartBtn AT %IX0.0 : BOOL; // DI 通道 0
bStopBtn AT %IX0.1 : BOOL; // DI 通道 1
wEncoder AT %IW10 : WORD; // AI 字 (encoder 值)
diPosition AT %ID20 : DINT; // AI 双字 (位置)
rTempSensor AT %IW100 : REAL; // AI 浮点 (4字节, 别名 %ID100)

// Q 区 — 物理输出
bMotor AT %QX0.0 : BOOL; // DO 通道 0
bValve AT %QX0.1 : BOOL; // DO 通道 1
wAnalogOut AT %QW10 : WORD; // AO 字
rSetPoint AT %QW200 : REAL; // AO 浮点

// M 区 — HMI 共享
bHMI_Start AT %MX0.0 : BOOL; // HMI 启动按钮
iRecipeNo AT %MW100 : INT; // HMI 配方选择
rSetTemp AT %MD200 : REAL; // HMI 温度设定
sMessage AT %MB300 : STRING[64]; // HMI 消息

// D 区 — 数据块
stBatch AT %D10.0 : ST_BatchRecord; // DB10 存批次记录

// S 区 — 系统变量 (只读)
tScanTime AT %SW0 : TIME; // 当前扫描时间
iCpuLoad AT %SW2 : INT; // CPU 负载 0-100%
END_VAR

地址语法

%<区域><大小><偏移>[.<位>]

区域: I, Q, M, D, S
大小: X (位), B (字节), W (字, 2B), D (双字, 4B), L (长字, 8B)
偏移: 字节偏移 (0 开始)
位: 0-7 (仅 X 格式需要)

示例:
%IX0.0 → I 区第 0 字节的 bit 0
%IW10 → I 区第 10~11 字节组成的字
%MD200 → M 区第 200~203 字节组成的双字
%D10.DBW0 → 数据块 DB10 的第 0 字节起的字
地址重叠

不同大小标识可能访问同一内存, 例如:

地址物理位置
%MB0M 区字节 0
%MB1M 区字节 1
%MW0M 区字节 0~1 (= MB0 高 + MB1 低)
%MD0M 区字节 0~3
%MX0.0M 区字节 0 的 bit 0

如果同时声明 iCount AT %MW0bFlag AT %MX0.0, 两个变量占用同一块内存, 容易互相覆盖。编译器的 IOConflictChecker 会警告此类重叠。

截图: 数据块编辑器

变量表 (PLCVariableTable)

变量表是 PLC 程序中所有变量的集中注册中心:

功能说明
符号解析变量名 ↔ 内存地址双向查找
类型检查编译时和运行时类型验证
地址分配自动为变量分配 M/V 区地址
监视支持在线调试时读取/强制变量值
导入导出CSV/Excel 批量编辑变量
交叉引用定位每个变量的所有读写位置

变量表界面提供以下列:

截图: 变量表

列名说明
名称变量符号名
类型BOOL / INT / REAL / 自定义
地址%Mxxx 或自动分配
初始值启动时的初始化值
属性RETAIN / PERSISTENT / CONSTANT
注释中文描述
范围最小值 / 最大值 (用于校验)
单位工程单位 (℃ / mm / rpm)

命名约定 (匈牙利前缀)

推荐使用匈牙利前缀提高代码可读性:

前缀类型示例
bBOOLbStart, bReady
byBYTEbyStatus
siSINTsiTemp
iINTiCount
diDINTdiPosition
liLINTliTimestamp
uiUINTuiSpeed
udiUDINTudiEncoder
wWORDwStatus
dwDWORDdwControl
rREALrTemp
lrLREALlrAngle
sSTRINGsName
tTIMEtDelay
a / arARRAYaiData, arMatrix
stSTRUCTstMotor
eENUMeState
fbFB 实例fbPID
p指针pBuffer

全局变量加 g 前缀 (giCounter), RETAIN 加 r 前缀 (riTotal)。

排错表

问题原因解决
变量未声明错误忘了在 VAR 区声明补充声明
地址冲突警告%MW0%MB0 重叠重新分配地址
初始值未生效热重启未冷启动切冷启动或手动复位
RETAIN 丢失NVRAM 电池耗尽检查硬件, 换备份电池
VAR_IN_OUT 改到源传参按引用的副作用改用 VAR_INPUT 按值传递
枚举值比较错误忘加类型前缀E_State.IDLE 而非 IDLE

相关文档