第三章 编程基础之数据类型:位、字节、字、双字、整型、浮点型、时间与日期类型、用户自定义数据类型(UDT)

各位学员,欢迎来到数据类型这一章。说实话,数据类型是编程的基石,就像盖房子用的砖头。砖头选不对,房子迟早要塌。我在西门子自动化这行摸爬滚打十几年,见过太多因为数据类型搞错而导致的现场故障。今天咱们就把这块硬骨头啃下来。

3.1 位、字节、字、双字——PLC里的“度量衡”

先聊聊最基础的数据单位。PLC里数据怎么存?说白了,就是一堆开关的通断。

  • 位(Bit):最小的数据单位,只有0或1。我习惯叫它“开关量”。比如一个按钮按下去,对应的位就是1;松开就是0。
  • 字节(Byte):8个位组成一个字节。范围0~255。嗯,这里要注意,字节在PLC里常用来存小数值,比如一个工位的状态码。
  • 字(Word):16个位,也就是2个字节。范围0~65535。我记得有一次做项目,用字来存一个编码器的脉冲数,结果没考虑正负,差点出事故。
  • 双字(DWord):32个位,4个字节。范围0~4294967295。大数值,比如累计产量、高速计数器,都得用它。

避坑指南:我曾经在调试一个包装线时,把双字当字用了。结果计数器到65535就归零了,整条线停了半小时。从那以后,我每次定义变量都会先问自己:这个数最大能到多少?

3.2 整型——有符号的世界

刚才说的字和双字都是无符号的,只能存正数。但现实世界有正负啊,比如温度、位置偏差。这时候就需要整型了。

类型 位数 范围 我的建议
SInt 8 -128 ~ 127 很少用,除非内存紧张
Int 16 -32768 ~ 32767 最常用,模拟量、计数器首选
DInt 32 -2147483648 ~ 2147483647 大范围数值,比如位置控制

我个人习惯是:能用Int就不用SInt。为什么?因为SInt范围太小,一不小心就溢出了。你想想看,一个温度传感器输出-50到150度,用SInt的127上限,夏天一热就炸了。

3.3 浮点型——带小数点的精度

整型只能存整数,那小数怎么办?比如压力值12.5兆帕,转速1500.3转/分。这时候就得请出浮点型了。

博途里浮点型就是Real,32位。精度大概6~7位有效数字。够用吗?说实话,99%的工业场景都够。但要注意一点:浮点数比较时别用“等于”,要用“接近”。

我的小技巧:比较两个浮点数是否相等时,我通常这样写:ABS(Value1 - Value2) < 0.001。这样就不会因为精度问题导致逻辑误判。

3.4 时间与日期类型——让PLC知道“现在几点”

工业现场经常需要定时、延时、记录时间戳。博途提供了几种时间类型:

  • Time:以毫秒为单位的有符号双整数。范围从 -24天20小时31分23秒647毫秒 到 +24天20小时31分23秒647毫秒。我常用它做定时器。
  • Date:以天为单位,从1990年1月1日开始算。范围1990-01-01 到 2168-12-31。记录生产日期很方便。
  • DTL:精确到纳秒的结构体。包含年、月、日、时、分、秒、纳秒。嗯,这个有点大材小用,一般用在高速数据采集上。

我记得有一次做食品追溯系统,要求记录每个产品包装的精确时间。用Date加Time组合,完美解决。但要注意,PLC断电后时间会丢失,需要配UPS或者用NTP同步。

3.5 用户自定义数据类型(UDT)——你的专属“乐高积木”

前面讲的都是基础类型,但实际项目里,数据往往是成组出现的。比如一个电机,有启停命令、速度给定、电流反馈、温度反馈。难道要定义四个独立的变量?太乱了。

UDT就是解决这个问题的。你可以把相关的数据打包成一个“结构体”。

// 定义一个电机控制UDT
TYPE "MotorControl"
    Command : Bool;      // 启停命令
    SpeedSetpoint : Int; // 速度给定
    CurrentFeedback : Real; // 电流反馈
    Temperature : Real;  // 温度反馈
    Fault : Bool;        // 故障标志
END_TYPE

定义好后,你就可以像使用普通变量一样使用这个UDT。比如声明一个“Motor1”变量,类型就是“MotorControl”。然后通过Motor1.CommandMotor1.SpeedSetpoint来访问内部元素。

重要提醒:UDT一旦定义并投入使用,修改时要特别小心。我曾经在项目中期给UDT增加了一个字段,结果所有使用该UDT的DB块都需要重新编译,差点耽误交货。所以,前期规划一定要做足。

3.6 实战中的数据类型选择策略

讲了这么多,到底怎么选?我总结了几条经验:

  1. 开关量用Bool:别用Int代替,浪费内存还容易混淆。
  2. 模拟量用Int或Real:0~10V、4~20mA的信号,用Int就够了。需要高精度或计算时用Real。
  3. 计数器用DInt或UDInt:别用Int,容易溢出。我见过有人用Int存产量,一天就溢出了。
  4. 时间相关用Time:别自己算毫秒,博途的Time类型直接支持加减运算。
  5. 复杂对象用UDT:比如一个工位、一台设备、一个配方。用UDT管理,程序结构清晰,维护方便。

好了,数据类型就讲到这里。下一章咱们聊聊变量声明和寻址方式。记住,数据类型是基本功,练扎实了,后面写程序才能行云流水。