3. PLC变量与数据类型
在S7-1200的编程中,变量是程序操作的最小对象,而数据类型决定了这个对象占多少存储空间、能表示什么范围的值、以及能参与哪些运算。很多初学者写程序时只关心“逻辑对不对”,忽略了数据类型,结果出现数值溢出、精度丢失、字符串乱码、数组越界等问题。本节把S7-1200常用的数据类型按“位—字节—字—双字”的存储层次和“基本类型—复合类型—用户自定义类型”的抽象层次两条线索讲清楚,并说明变量表的管理方法。
一、按位组织的存储单位:位、字节、字、双字
S7-1200的存储区按位(Bit)寻址,8个连续位组成1个字节(Byte),2个字节组成1个字(Word),2个字组成1个双字(DWord)。它们的关系是:1字节=8位,1字=16位,1双字=32位。位地址写作M0.0、I0.3、Q1.7,字节地址写作MB10,字地址写作MW10,双字地址写作MD10。
这里有一个必须记住的“重叠”关系:MW10由MB10和MB11组成,MD10由MB10、MB11、MB12、MB13组成。也就是说,对MD10写值会同时改变MW10、MW12、MB10~MB13的内容。编程时如果既用MD10又用MW12,就会互相干扰。这是变量表管理中要重点检查的“地址重叠”问题。
二、基本数据类型:整数、浮点数、字符串
整数类型按位宽和符号分为:Bool(1位,TRUE/FALSE)、Byte(8位无符号,0~255)、Word(16位无符号,0~65535)、DWord(32位无符号)、SInt(8位有符号,-128~127)、Int(16位有符号,-32768~32767)、DInt(32位有符号)。选择原则是:先看数值范围,再看是否需要负数,最后看运算精度。
浮点数用于表示带小数的物理量,S7-1200支持Real(32位,约6~7位有效数字)和LReal(64位,约15位有效数字)。模拟量采集、PID运算、流量累计等场合必须用浮点数。要注意Real不能直接与Int比较或运算,需要先用CONV指令转换,例如把Int转成Real再参与除法,否则会得到整数除法的截断结果。
字符串类型有String和WString。String默认最大长度254个字符,每个字符占1字节;WString每个字符占2字节,适合中文等多字节字符。字符串变量在变量表中声明时要指定最大长度,例如String[20]表示最多20个字符。字符串比较用==、<>,拼接用CONCAT,取子串用LEFT、RIGHT、MID。
三、复合数据类型:数组与结构体
数组(Array)把同类型的多个元素连续存放,声明格式为Array[0..9] of Int,表示10个Int元素,下标从0到9。数组元素用数组名[下标]访问,例如Temp[3]。数组适合存放一批同性质的数据,如10个温度采集值、8个工位状态。使用数组时下标不能越界,否则CPU会报“区域长度错误”并进入STOP。
结构体(Struct)把不同类型的多个元素组合成一个整体,声明格式为Struct,内部包含若干成员,例如一个电机结构体包含Start : Bool、Speed : Real、Current : Real、Fault : Bool。结构体适合描述一个设备或一个对象的完整属性,访问时用结构体名.成员名,例如Motor1.Speed。数组和结构体可以嵌套,例如Array[1..4] of Motor表示4台电机。
四、PLC数据类型(UDT)与变量表管理
当多个结构体成员完全相同时,可以定义PLC数据类型(UDT,用户自定义数据类型)。在TIA Portal的“PLC数据类型”中新建UDT,例如命名为UDT_Motor,内部定义Start、Speed、Current、Fault四个成员。之后在变量表中声明变量时,数据类型直接选择UDT_Motor,就能一次生成整套成员。UDT的好处是:修改一次定义,所有使用该UDT的变量同步更新,避免逐个修改。
变量表(PLC变量表)是管理变量地址、名称、数据类型、注释的地方。建议按功能分区建立多个变量表,例如“输入变量”“输出变量”“中间变量”“HMI变量”。命名采用“设备_功能_类型”的规则,如M1_Start、M1_Speed,避免使用Tag_1这类无意义名称。变量表中要检查地址是否重叠、数据类型是否与使用场合匹配、注释是否完整。
五、变量表管理中的常见问题与检查方法
变量表管理最容易出三类问题。第一类是地址重叠:例如同时声明了MD100和MW102,两者共享MB102和MB103,程序运行时互相覆盖。检查方法是按地址排序,观察是否有双字、字、字节地址落在同一区间。第二类是数据类型不匹配:例如把Int变量直接连到Real输入引脚,编译时会报“类型不兼容”。解决方法是插入CONV或NORM_X、SCALE_X指令。第三类是数组越界:例如声明Array[0..9]却访问Temp[10],CPU会报区域长度错误。检查方法是核对循环变量的上下限。
实用建议:在变量表中为每个变量写清楚注释,注明量纲和范围,例如“M1_Speed:电机1转速,单位r/min,范围0~1500”。对于模拟量输入,建议在变量表中直接声明为Int,再用NORM_X和SCALE_X转换成工程量Real,这样变量表本身就能反映信号链的转换关系。
下面给出一个变量表片段示例,展示电机控制中常用的变量声明方式。示例中的地址和参数为教学假设值,实际项目需根据硬件组态和工艺要求调整。
名称 数据类型 地址 注释
M1_Start Bool %I0.0 电机1启动按钮
M1_Stop Bool %I0.1 电机1停止按钮
M1_Fault Bool %I0.2 电机1故障反馈
M1_Run Bool %Q0.0 电机1运行输出
M1_Speed_SP Real %MD100 电机1速度设定值 r/min
M1_Speed_PV Real %MD104 电机1速度实际值 r/min
M1_Current Real %MD108 电机1电流 A
M1_Data UDT_Motor %MD200 电机1完整数据块
Temp_Array Array[0..9] of Real %MD300 10点温度采集
Recipe_Name String[20] %MB400 配方名称
从这张表可以看出,M1_Data使用UDT后,一个变量就包含了启动、速度、电流、故障等成员,访问时写作M1_Data.Speed、M1_Data.Fault。这样变量表更简洁,程序可读性也更高。当需要增加“电机温度”成员时,只需修改UDT_Motor定义,所有使用该UDT的变量自动获得新成员,不需要逐个变量修改。
最后强调一个原则:数据类型的选择要“够用就好”,不要一律用Real或DInt。位信号用Bool,计数器用Int或DInt,模拟量工程量用Real,文本用String,成组数据用数组或结构体,重复结构用UDT。变量表按功能分区、命名规范、注释完整,是后续编写程序、调试和交接的基础。