第四章 数据块与变量表:PLC的“记忆仓库”与“通讯录”
各位工程师朋友,大家好。欢迎来到第四章。
这一章,咱们聊聊PLC程序里最基础、也最核心的东西——数据。你想想看,程序跑得再花哨,最终不就是为了处理数据吗?S7-1200和1500里,数据怎么存、怎么管、怎么找,全靠数据块和变量表。我刚开始用西门子的时候,也在这上面栽过跟头,今天就把这些经验掰开揉碎了讲给你听。
核心一句话:数据块是仓库,变量表是通讯录。仓库里放什么、怎么放,通讯录怎么编,决定了你的程序好不好维护、会不会出bug。
4.1 全局数据块(DB)—— 你的“共享仓库”
全局数据块,英文叫Data Block,简称DB。说白了,就是一块专门用来存数据的“共享内存区”。
我个人习惯,把所有需要跨程序块共享的数据,都放在全局DB里。比如设备的状态字、工艺参数、配方数据等等。为什么?因为全局DB里的数据,整个PLC程序都能访问,不用像M区那样担心地址冲突。
我的经验:我曾经在一个大型项目中,把所有模拟量通道的标定值都放在一个全局DB里。后来现场要改量程,只需要在线修改DB里的几个Real数,不用动程序。甲方看了直呼内行。
创建全局DB很简单:在项目树里右键“添加新块”,选“数据块(DB)”,类型选“全局DB”。然后你就可以在里面定义变量了。
举个例子,一个电机控制的数据块:
// 电机控制数据块 (DB_MotorControl)
DATA_BLOCK "DB_MotorControl"
{ S7_Optimized_Access := 'TRUE' } // 优化访问,性能更好
VERSION : 0.1
STRUCT
Start_Button : Bool; // 启动按钮
Stop_Button : Bool; // 停止按钮
Motor_Running : Bool; // 电机运行状态
Speed_Setpoint : Real; // 速度设定值 (rpm)
Speed_Actual : Real; // 速度实际值 (rpm)
Run_Hours : UDInt; // 累计运行时间 (秒)
Fault_Code : Word; // 故障代码
END_STRUCT;
END_DATA_BLOCK
注意:S7-1200/1500默认开启了“优化块访问”。这意味着你不能像200 SMART那样直接用“DB1.DBW0”这种绝对地址来访问。必须用符号名,比如“DB_MotorControl.Speed_Setpoint”。刚开始可能不习惯,但相信我,这能让你少掉很多头发。
4.2 背景数据块——FB的“私人秘书”
背景数据块,也叫Instance DB。它和全局DB最大的区别是:它不独立存在,必须依附于一个函数块(FB)。
你想想看,FB就像一个“模板”,它定义了逻辑,但每个实例需要自己的数据存储空间。这个空间,就是背景数据块。
比如你写了一个“电机控制”的FB,里面有启动、停止、速度控制逻辑。然后你现场有10台电机,每台电机都需要独立的运行状态、速度值。这时候,你只需要调用10次这个FB,每次调用时系统自动生成一个背景数据块。每个背景数据块里存的是对应电机的私有数据。
核心区别:全局DB是“公共储物柜”,谁都能用。背景DB是“私人保险箱”,只有对应的FB实例才能用。
我记得有一次,一个新手同事把所有电机数据都放在一个全局DB里,然后FB里用数组索引来区分。结果程序一复杂,索引搞错了,电机乱转。后来我让他改成背景数据块,每个电机一个实例,清清楚楚,再也没出过问题。
4.3 PLC变量表——你的“通讯录”
PLC变量表,也叫符号表。它的作用,就是给PLC的物理地址起个“人话”名字。
比如,数字量输入I0.0,你给它起名叫“急停按钮”。这样在程序里写“急停按钮”比写“I0.0”直观多了吧?
变量表里可以定义:
- 输入(I):传感器、按钮等输入信号
- 输出(Q):继电器、指示灯等输出信号
- 位存储(M):中间变量
- 定时器(T)、计数器(C):时间与计数
- 数据块(DB):也可以在这里给DB起别名
来看一个典型的变量表定义:
| 符号 | 地址 | 数据类型 | 注释 |
|---|---|---|---|
| 急停按钮 | I0.0 | Bool | 红色蘑菇头按钮,常闭 |
| 启动按钮 | I0.1 | Bool | 绿色按钮,常开 |
| 电机运行灯 | Q0.0 | Bool | 绿色指示灯 |
| 故障灯 | Q0.1 | Bool | 红色指示灯 |
| 模拟量输入1 | IW64 | Int | 4-20mA压力传感器 |
| 模拟量输出1 | QW64 | Int | 变频器速度给定 |
我的习惯:变量表里的注释一定要写清楚。别偷懒。我曾经在调试一个老外的项目时,看到注释写的是“Don't touch this”,结果我查了半天才发现是个安全互锁。从那以后,我要求团队所有注释必须写明白“是什么、为什么、怎么用”。
4.4 数据类型——数据的“身份证”
PLC里的数据类型,决定了数据怎么存、占多大空间、能干什么运算。S7-1200/1500支持的数据类型很丰富:
- 基本类型:Bool(位)、Byte(字节)、Word(字)、DWord(双字)、Int(整数)、DInt(双整数)、Real(浮点数)
- 时间类型:Time(时间,单位ms)、Date(日期)、TOD(一天中的时间)
- 字符串:String、WString(Unicode字符串)
- 复合类型:Array(数组)、Struct(结构体)
这里有个坑,我必须要说:数据类型不匹配,是PLC程序最常见的bug之一。
比如,你把一个Int(-32768到32767)的值赋给一个Real变量,没问题。但反过来,你把一个Real(比如3.14)赋给一个Int,PLC会直接截断小数部分,变成3。如果你没意识到,后面算比例、算累计,结果全错。
避坑指南:我曾经在做一个流量累计程序时,把累计值定义成了Int。结果流量一超过32767,累计值直接变成负数。现场操作员以为管道倒流了,吓得按了急停。后来我改成DInt,再也没出过这种笑话。
4.5 数组——数据的“书架”
数组,就是把同一类型的数据排成一排,用索引来访问。比如,你有10个温度传感器,不用定义10个单独的变量,定义一个数组就够了:
// 温度数组定义
Temp_Sensor : Array[1..10] of Real; // 10个温度值,索引1到10
访问的时候:
#Temp_Value := "DB_Temp".Temp_Sensor[3]; // 读取第3个温度传感器
数组在批量处理时特别有用。比如用FOR循环遍历所有温度:
FOR #i := 1 TO 10 DO
IF "DB_Temp".Temp_Sensor[#i] > 100.0 THEN
// 超温报警逻辑
END_IF;
END_FOR;
注意:S7-1200/1500的数组索引可以从任意整数开始,不一定非要从0或1开始。我个人习惯从1开始,更符合工程直觉。
4.6 结构体——数据的“文件柜”
结构体,就是把不同类型的数据打包成一个整体。比如,一个“电机”的数据,有启动按钮(Bool)、速度(Real)、运行时间(UDInt)……用结构体把它们装在一起:
// 电机数据结构体
TYPE "Motor_DataType"
STRUCT
Start_Button : Bool;
Stop_Button : Bool;
Speed : Real;
Run_Hours : UDInt;
Fault_Code : Word;
END_STRUCT;
END_TYPE
然后在DB里直接使用这个结构体:
DATA_BLOCK "DB_MotorData"
Motor1 : "Motor_DataType"; // 电机1
Motor2 : "Motor_DataType"; // 电机2
Motor3 : "Motor_DataType"; // 电机3
END_DATA_BLOCK
访问的时候:
"DB_MotorData".Motor1.Speed := 1500.0; // 设置电机1的速度
结构体最大的好处是:复用性和可读性。你定义一次结构体,可以在多个DB、多个FB里反复使用。而且程序里一看就知道这个变量属于哪个设备,逻辑清晰得很。
我的建议:在项目开始前,花半小时把常用的结构体定义好。比如“电机数据类型”、“阀门数据类型”、“模拟量通道数据类型”。这半小时,能让你后面省下几十个小时的调试时间。
4.7 数组与结构体组合——真正的“数据矩阵”
把数组和结构体组合起来,威力更大。比如,一个生产线有20台电机,每台电机都有相同的属性:
DATA_BLOCK "DB_LineMotors"
Motors : Array[1..20] of "Motor_DataType"; // 20台电机的数据
END_DATA_BLOCK
访问第5台电机的速度:
"DB_LineMotors".Motors[5].Speed := 1200.0;
用循环批量处理所有电机:
FOR #i := 1 TO 20 DO
IF "DB_LineMotors".Motors[#i].Fault_Code <> 0 THEN
// 记录故障电机编号
END_IF;
END_FOR;
这种结构,在大型项目中几乎是标配。我做过一个汽车焊装线的项目,光电机就300多台,全是靠这种“结构体数组”来管理的。程序写起来快,查起来也快。
好了,这一章的内容就到这里。数据块和变量表是PLC编程的基石,你花多少时间在上面都不为过。记住:好的数据结构,是优秀程序的一半。
下一章,咱们聊聊函数块和函数——怎么把逻辑封装成可复用的“积木”。
公众号:蓝海资料掘金营,微信deep3321