PLC编程必学:进制转换与数据类型详解

发布时间:2026/9/1 2:26:24
PLC编程必学:进制转换与数据类型详解 第二十三讲 PLC编程进制转换与数据类型1. PLC编程中为什么一定要掌握进制转换与数据类型很多初学者在接触PLC的第一周都会产生一个疑问梯形图看起来明明是一堆触点和线圈怎么还跟“进制”和“数据类型”扯上关系了甚至有同学把程序写完之后发现数值对不上、通信读出来全是乱码、模拟量换算总是偏差几倍最后查来查去问题根本不是出在逻辑上而是出在“数据类型和进制”上。先给一个明确判断PLC程序表面上写的是逻辑底层跑的全是数据。你写的每个触点、每个比较指令、每个传送指令本质上都在操作一段二进制数据。而进制转换和数据类型恰恰是串起软元件地址、数据长度、通信协议、模拟量采样的那条主线也是从“会看梯形图”进阶到“能独立做项目”的第一道分水岭。这篇文章会把进制转换和数据类型放到真实的PLC编程场景里来讲而不是像数学课一样只列一张换算表。重点解决几个实际痛点理解二进制、十六进制和PLC位号、字地址、寄存器之间的关系。说清楚位、字节、字、双字的数据长度区别以及为什么同样的数值在不同长度下含义完全不同。结合西门子和三菱PLC梳理常见的软元件数据类型差异。解决实际项目中频繁遇到的数据类型不匹配、强制转换、Modbus通信数据解析问题。最后给出一个可以直接照用的学习路径和排查清单。如果你正在学PLC编程入门或者已经在做项目但经常在数据类型上踩坑建议把这篇收藏起来当成一份查漏补缺的参考。2. 数制基础二进制、八进制、十进制、十六进制的关系2.1 为什么PLC内部只认二进制PLC的核心是微处理器而微处理器唯一能识别的就是“开关状态”——高电平为1低电平为0。所以从物理层面看PLC内部所有的数值、状态、数据都只能以二进制形式存在。梯形图里的X0、Y0触点本质是某一个存储位上的0或1。二进制的好处是直观对应硬件的开关状态缺点是位数一多写起来太累。比如十进制数200写成二进制是11001000肉眼几乎看不出它有多大。为了解决“人能看清、机器能运算”的矛盾工程上引入了十六进制用4位二进制对应1位十六进制数这样无论是看监视值还是写地址人都能轻松处理。2.2 二进制、八进制、十进制、十六进制对照先把四个数制放在一张表里这张表建议保存下来写程序时经常用到。十进制二进制八进制十六进制00000001000111200102230011334010044501015560110667011177810001089100111910101012A11101113B12110014C13110115D14111016E15111117F注意一个容易混淆的点十六进制的10到15是用A、B、C、D、E、F表示的在PLC程序里十六进制数据一般会加前缀或后缀标明。三菱PLC里十六进制数用H前缀比如H1F西门子PLC里常用16#1F比如16#FF表示255。如果没写前缀PLC会默认按十进制处理这是新手最容易忽略的地方。2.3 八进制在PLC里的特殊含义二进制每3位一组就是八进制但在现代PLC里八进制更多是被“地址编号习惯”带出来的而不是真正的运算选择。三菱PLC的输入继电器X、输出继电器Y的编号经常带有“八进制进位”的影子例如X0到X7之后是X10而不是X8、X9。很多初学者第一次看到三菱PLC的X7之后直接跳到X10会以为是编号写错了其实这是老式PLC延续下来的编号习惯。实际写程序时不需要刻意计算八进制但调试时看到地址跳号不要慌这是正常的。3. PLC里最常见的数据长度单位位、字节、字、双字3.1 位、字节、字、双字的定义先把数据长度捋清楚。PLC编程中所有数据都可以按照长度来分类具体对应关系如下数据单位二进制位数取值范围对应PLC资源示例位(Bit)1位0或1三菱X、Y、M西门子I、Q字节(Byte)8位0~255无符号西门子MB0、三菱部分指令按字节处理字(Word)16位0~65535无符号三菱D、西门子MW0双字(Double Word)32位0~4294967295无符号三菱DD1组合、西门子MD0这里的“字”是最容易产生误解的地方。很多刚入门的朋友会问一个字不就16位吗为什么有的PLC里写一个数据寄存器就够有的要一次写两个原因在于一个16位字能表示的整数范围只有 -32768到32767有符号或0到65535无符号。如果项目里出现了大于这个范围的数值比如流量计的累积量、编码器的大范围计数值就必须用双字。三菱PLC里的32位数据通常要用两个连续的数据寄存器比如D0和D1组合成32位西门子PLC里双字就是MD0这种形式同样要占用4个字节的地址空间。3.2 数据长度与地址重叠问题这里有一个实际项目中特别常见的坑地址重叠。以西门子PLC为例MB0、MW0、MD0这三个地址指向的内存起始位置是一样的。MB0是第0号字节MW0是第0号和第1号字节MD0是第0号到第3号字节。如果你在程序里既用了MW0又用了MD0那么两者会互相覆盖最后看到的数值完全是乱的。正确做法是大范围数据和小范围数据不要用同一个起始地址。比如你用了MD0作为双字那么MW0、MB0、MB1就尽量不要在其他地方单独使用。在很多PLC项目规范里会要求“双字地址必须对齐且该地址区域不允许再拆分使用”。三菱PLC同样如此当你用D0和D1组成32位数据时D0和D1就不能再被其他指令绕过组合规则单独乱写。编程软件通常不会强制报错但运行起来数据错乱是必然的。4. PLC核心数据类型从布尔到实数4.1 布尔型最简单也最容易忽略布尔型BIT只有0和1两种状态对应PLC里的触点、线圈、内部继电器。在梯形图中它的表现最直观得电为1失电为0。但即使是最简单的布尔量也有需要注意的地方。比如三菱PLC的M0和西门子PLC的M0.0虽然都叫M但一个是独立的内部继电器一个是某个字节里的一位。如果拿西门子的M0.0去对应三菱的M0需要先搞清楚项目里有没有做“地址映射表”否则跨品牌移植程序时极易混淆。4.2 整数类型INT、DINT与长度整数类型在PLC里分为几种类型长度有符号范围典型应用INT16位-32768~32767普通计数、定时值、频率设定DINT32位-2147483648~2147483647累积量、大范围位置值UINT16位0~65535无符号计数、某些通信寄存器值UDINT32位0~4294967295大范围无符号累加实际项目中定时器当前值、计数器当前值通常就是以整数形式存储的。如果你需要把定时器的值放到触摸屏上显示数据类型要保持一致如果触摸屏上要显示小数那还需要额外做一次整数到实数的转换。4.3 实数带小数的数据必须用REAL实数是PLC里相对高级一点的数据类型在西门子PLC里叫REAL在很多国产PLC里也叫FLOAT本质是32位浮点数。只要涉及温度、压力、流量、速度或比例计算基本上都逃不开实数。举个例子模拟量采集模块读到0到4000的原始值你要把它换算成0到10V的电压就会用到除法和乘法。如果直接拿整数做除法结果会被截断比如3除以2得到1而不是1.5。此时必须先进行类型转换把整数转成实数再参与运算最后再转回整数或保留实数显示。这也是很多项目里“明明公式没错结果却不对”的经典原因。4.4 数据类型长度和Modbus通信的关系搜索热词里有一条“modbus数据类型长度默认为多长”这里一并讲清楚。Modbus协议本身定义了几种基本数据对象线圈、离散输入、保持寄存器、输入寄存器。其中线圈和离散输入是按位操作的只有0和1两种状态保持寄存器和输入寄存器按字操作每字16位。因此你在做PLC与仪表、变频器或上位机通信时会看到这样的现象读一个开关状态对应Modbus里的一个线圈或离散输入数据长度1位。读一个温度值对应Modbus里的一个保持寄存器数据长度16位。读一个累积量可能占用两个连续的保持寄存器数据长度32位。这个“32位数据占用两个寄存器哪个寄存器是高字、哪个是低字”的问题就是通信调试里最经典的字节序问题。不同设备厂家对寄存器内部字节顺序的定义不一样有的是低字节在前有的是高字节在前。如果没做转换读出来的数据会变得非常大或非常小。排查时优先检查字节顺序和寄存器长度能省很多时间。4.5 BCD码PLC和触摸屏编码里经常出现的特殊编码BCD码以4位二进制表示1位十进制数比如十进制25用BCD码表示就是0010 0101。它本身不是一种数据类型而是一种编码方式。三菱PLC的七段码显示、部分触摸屏的地址设定、以及某些拨码开关输入模块都直接或间接用到BCD码。用BCD码的好处是调试时从监控软件里看到的数据和十进制几乎一致肉眼友好。代价是BCD码不能直接参与数学运算必须先转换成普通二进制整数后再计算否则加减乘除结果会错得很离谱。在程序里三菱PLC有BIN指令和BCD指令用来做二进制与BCD码互转西门子PLC也有对应的转换功能块。看到程序里出现BCD字样先确认它是在做编码转换不要当成普通的数值传送。5. 进制转换在PLC编程中的实际应用场景理解了数制和数据类型之后接下来看它们到底用在哪些环节。这里列举四个真实场景每一个都是项目里绕不开的。5.1 场景一触摸屏和设备地址的十六进制设定很多变频器、伺服驱动器的参数设定界面里地址是以十六进制显示的。比如伺服驱动器的一个状态字地址是0x6041你需要在PLC程序里对这个地址写入或读取数据。如果不懂十六进制看到6041就会想当然以为是一万多的十进制数据然后拿着这个数值在程序里找半天都找不到。实际工作中要做的第一件事是把十六进制地址与PLC软元件地址对应起来再根据寄存器长度确认数据类型。地址对应错了后面一切通信都白搭。5.2 场景二Modbus通信中的数据解析假设PLC作为主站读取一个第三方温控表的Modbus寄存器。协议文档里写寄存器地址0x0001数据类型为16位无符号整数数值乘以0.1就是实际温度。你读回来的原始值是十六进制0x0123换算成十进制是291再乘以0.1就得到29.1摄氏度。整个过程里“十六进制转十进制”和“整数乘系数”是两步必不可少的操作。如果原始值是32位浮点数或32位整数还需要按地址顺序把两个16位寄存器拼成一个32位数据再处理字节序。5.3 场景三模拟量输入的工程量转换模拟量通道一般读到的是一个0到4000、0到20000或0到27648的整数原始值。要把这个整数转换为真实的压力、温度或流量值标准做法是线性映射公式工程量 最小值 原始值 - 量程下限×最大值 - 最小值 / 量程上限 - 量程下限在这个公式里所有输入都必须先转成浮点数否则整数相除会丢失小数部分。做完除法得到结果后再根据显示需要来选择保留整数还是转成实数。这一步是“数据类型转换”最典型的应用也是初学者最容易在除法和截断上翻车的地方。5.4 场景四机械手位置数据和包装数量的数据处理机械手PLC编程里位置数据通常涉及绝对位置和相对位置数据类型可能是32位整数也可能是32位实数。包装计数通常用32位整数因为数量可能超过32767。如果程序中把计数器的值赋给了一个16位整数变量超过范围后数值会翻转可能是负数也可能是完全不对的大数字。所以在做机械手相关项目时位置、速度、计数三类数据必须提前规划好数据类型速度常用实数位置根据行程大小选择32位整数或实数计数通常选32位整数。6. 西门子与三菱PLC数据类型差异对照做PLC项目的人很多时候会在西门子和三菱两个平台之间切换。如果只理解一套PLC的数据类型切换到另一套时就会踩坑。这里从数据类型角度做一个对照。对比维度西门子PLC三菱PLC位软元件I、Q、MX、Y、M字节地址MB0较少单独用字节寻址三菱字节指令相对有限字地址MW0D0双字地址MD0D0D1组合16位数据表示十进制、16#十六进制十进制、H十六进制实数REAL32位浮点数通常占用DD1两个寄存器定时器编号T0等类型为定时器T0等类型为定时器三菱高速计数器编号—C235等编程软件中的格式常显DEC/HEX/BIN/FLOAT常显DEC/HEX/BIN/FLOAT从结构上看西门子PLC的内存管理更像“统一编址”字节、字、双字可以灵活重叠使用但必须严格控制重叠区域三菱PLC的数据寄存器D是16位为基本单位32位数据天然要占两个D。实际项目中如果团队有人用西门子、有人用三菱最好在程序开头写清楚“数据长度规划表”否则后续做设备联调时每个人对“一个数据占几个字”的理解不一样很容易出错。下面分别给出两个平台的简单编程示例演示数据传送和类型转换的基本思路。6.1 三菱PLC示例十六进制传送与32位传送// 三菱GX Works系列 梯形图/ST接近的指令写法 // 将十六进制数 H1234 传送到 D0 MOVP H1234 D0 // 将 D0 和 D1 组合成32位数据传送给 D10 和 D11 DMOVP D0 D10 // 将 D10 的值转换成BCD码后送入 D20 // 适合需要BCD码显示的场合 BCD D10 D20这段代码里前三行都是很常见的传送指令。DMOVP是多字传送指令执行后D10对应D0的数据D11对应D1的数据。如果在程序里只用了MOVP D0 D10那么D11不会跟着变化高位数据就丢失了。三菱FX系列的32位数据结果监控需要在软件里把数据格式改成32位整数或浮点数否则监控窗口里看到的只是D0单独的值很容易误判。6.2 西门子S7-1200/1500示例整数转实数// 文件路径OB1 或 FC 的临时变量区 #tempInt : INT; // 16位整数 #tempReal : REAL; // 32位实数 // 梯形图中调用转换指令 // INT - REAL 转换 L #tempInt ITD // 先转为32位整数 DINT DTR // 再转为 REAL T #tempReal这里需要注意在西门子PLC里直接从16位INT转换成REAL时有些指令集不支持一次完成通常要先转成DINT再转成REAL。原因在于浮点数的内部编码格式和整数完全不同需要经过中间类型过渡才能避免溢出和精度损失。TIA Portal里的转换指令通常在“指令”面板的“数学函数”或“转换操作”分类下可以直接拖拽。转换完成后建议在监控表里分别查看INT、DINT、REAL三个值确认每一步都符合预期。7. 数据类型与强制转换什么时候该转什么时候不该转7.1 隐式转换与显式转换很多高级语言的编译器会在整数和浮点数之间做隐式转换但PLC编程更偏保守。PLC程序要求数据长度和类型尽量明确因为不同品牌的PLC对转换的支持策略不一样。以西门子TIA Portal为例部分指令支持在梯形图连线时自动插入转换但系统也会给出提示三菱PLC则没有太多隐式转换很多时候需要手动加指令。在ST/SCL或结构化文本里你可以像高级语言一样直接写转换语句。// 西门子SCL示例 #RealValue : INT_TO_REAL(#IntValue); #IntValue2 : REAL_TO_INT(#RealValue);需要提醒的是把实数转成整数时默认会四舍五入到最近整数而不是直接截断小数。不同PLC对舍入规则的定义可能不同如果项目中有精度要求必须查清楚编程手册里的说明不能想当然。7.2 什么时候不该做强制转换强制转换不是万能的。有一个非常典型的错误场景把32位浮点数强转成16位整数导致溢出。比如温度值 1234.5 摄氏度通过REAL_TO_INT转成16位整数时如果PLC内部转换规则是先取整再判断范围结果可能直接变成 -32768 或 32767 这类边界值看起来像“数据乱跳”。实际情况是数据类型长度不够不是你程序逻辑错了。经验是先判断目标数据类型的范围再决定要不要转换。需要保留小数就继续用实数需要节省存储空间才考虑压缩成整数。为了“好看”而强行转换往往会把原本合理的数据变成错误数据。7.3 用监视表验证数据范围在调试时强烈建议在编程软件的监视表或监控窗口里同时按以下格式添加变量十进制格式DEC确认数值大小是否合理。十六进制格式HEX确认高低字节是否正常。二进制格式BIN确认具体的位状态。如果发现同一个地址在不同格式下看起来“对不上”并不是PLC出毛病了而是这些格式只是同一段数据的不同表现形式。真正要关心的是这段数据在程序里被当成了哪种数据类型来解读。8. 常见问题与排查思路下面把PLC编程中与进制转换、数据类型相关的常见问题整理成一张排查表实际写程序时遇到类似现象可以直接参考。问题现象可能原因排查方式解决方案数值显示为负数有符号数与无符号数解释不一致查看变量声明是否为INT或UINT按协议统一数据类型必要时用无符号类型监视窗口数值乱跳地址重叠或双字/字混用检查MB0、MW0、MD0是否同时使用重新规划地址大长度数据独占起始地址32位数据读出来只有高16位或低16位Modbus寄存器顺序或字序不对对比通信协议文档检查字节序在PLC或上位机端交换高低字3除以2得到1整数除法截断查看参与运算的变量类型先转为REAL再运算两个连续D寄存器组合后数值不对DMOV指令未使用只传了一个D查看程序里是MOV还是DMOV32位数据统一使用32位传送指令十六进制数值被当十进制处理缺少H前缀或16#前缀检查指令中数值写法三菱用H、西门子用16#模拟量换算偏差固定倍数原始值量程不匹配核对模拟量模块量程和公式参数统一量程上限修改线性换算参数BCD码显示后数值翻倍把BCD码当成普通二进制参与计算用监控软件查看BCD与BIN切换运算前转BIN显示前转BCD此外还有一个老生常谈但值得重复的问题PLC程序内部出现了错误提示但指令表里完全看不出语法问题。此时优先检查变量的数据类型是否匹配因为很多转换错误是在编译阶段才暴露的。9. 学习与实践建议9.1 建议一先建立一个数据规划表做任何PLC项目前先建立一张软元件和数据类型规划表把每个地址对应的功能、数据类型、数据范围、是否跨双字都写清楚。这个表不仅方便自己调试也方便团队协作和后期维护。很多老工程师能在现场快速定位问题靠的往往不是运气而是这种提前规划的习惯。9.2 建议二通过模拟量换算练手进制转换和数据类型最好的练手项目是模拟量工程值换算。你可以在PLC里写一个完整的小程序读取模拟量模块的原始值把它转成实数做线性映射再显示到触摸屏上。这个过程会覆盖整数、实数、除法、乘法、转换指令、量程匹配等多个知识点比死记硬背数据类型列表有效得多。9.3 建议三做通信工程时先看协议文档只要项目里涉及Modbus、串口或以太网通信第一步一定是找协议文档重点看三件事数据对象是位还是寄存器。每个数据占用几个寄存器。高低字节顺序是什么。这三件事确定之后再动笔写程序基本不会跑偏。9.4 建议四在编程软件里熟练使用监控和格式切换每位PLC开发者都应该熟练使用编程软件的监控表功能至少会在DEC、HEX、BIN、FLOAT四种格式之间切换并理解差异。看到十六进制数据能快速心算或者借助计算器转换看到寄存器值能判断它是16位/32位、是整数/浮点数。这种“数据敏感度”是PLC工程师的核心能力之一。回到开头那句话PLC程序的核心是数据。进制转换是理解数据的钥匙数据类型是定义数据的边界。把这两块掌握扎实后面无论是学通信、搞运动控制还是写复杂算法都会顺很多。建议你把这篇文章保存下来下次在项目里遇到地址不对、数值乱跳、模拟量算不准的问题时先翻出第三、第四、第八节的表格逐条对照。如果这篇文章对你有一点帮助也欢迎在评论区留言交流你平时遇到过哪些数据类型相关的坑。