ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

S7-1200数据块全解析:类型、访问方式与UDT设计实践

S7-1200数据块全解析:类型、访问方式与UDT设计实践 干过几年西门子项目的工程师基本都有体会程序逻辑写多了以后真正决定项目维护难度的往往不是那些FB、FC怎么调而是数据怎么组织。S7-1200的数据块Data Block有些老工程师习惯叫BD其实就是同一个东西看起来只是“存数据的格子”实际上一套设备的所有参数、中间变量、通讯报文都压在这块区域上。这篇东西想把S7-1200数据块从类型、访问方式、大小限制到建块的手法从头到尾捋清楚特别适合刚从S7-200 SMART转过来、还在用老思路建块的工程师也适合那些把DB当成“大号变量表”瞎用、后期被地址混乱和下载停机坑到想骂人的朋友。1. 数据块到底是什么它和“看到的所有变量放一起”完全是两码事1.1 全局DB、背景DB、UDT型DB三种块的分工完全不一样很多新手刚接触S7-1200时会觉得DB不就是个“变量仓库”嘛所有中间变量、设备参数、通讯数据一股脑建一个大的DB塞进去就行了。这个想法在小型项目里勉强能跑但一旦设备数量多了、程序要交付给别人维护这种一块走天下的做法就是灾难。S7-1200里的数据块从创建方式上分其实有三种完全不同用途的东西先说结论全局DB管设备级数据背景DB跟FB走UDT型DB则是最适合“一台设备一个块”的做法。第一种是全局DB你在TIA Portal里手动添加的数据块默认就是全局DB它不属于任何一个FB或FC全程序都可以访问。全局DB适合存放独立于逻辑块的数据比如整条产线的配方参数、HMI写入的设定值、上位机通讯的交互区这种数据的特点是没有明确的“归属对象”被很多块共用。第二种叫背景DB这个比较特殊是FB调用时自动生成的数据只在FB内部有意义比如写了一个“电机控制FB”每次调用都需要分配一个背景DB来保存这台电机的启停状态、运行时间、故障代码这个背景DB就是FB的功能记忆体。第三种是UDT型DB从S7-1200固件某个版本开始博途就支持了先自己定义一种用户数据类型UDT然后基于这个UDT创建数据块块里的结构就会自动带上UDT定义的所有字段。打比方说UDT相当于一张“设备信息表模板”DB就是按这个模板填出来的实际档案一台泵一张表十台泵就建十个基于同一UDT的DB。这三种DB在实际项目中往往是组合使用的设备相关数据用UDT型DB或背景DB跨设备交互的数据放全局DB。我见过不少项目把一百多台设备的参数全部塞进一个全局DB变量两三千个到后期上位机变量连接、程序内跨块引用都变得极其难查真出了故障定位哪台设备都费劲。正确做法是按设备类型划分每台设备一个DB再建一个公共通讯DB这样才能做到“看到DB名字就知道是哪个设备的数据”。1.2 数据库块区别于PLC变量表这个底层认知先建立起来S7-1200里有两个容易混的概念PLC变量表和数据块。PLC变量表PLC tags主要是给程序里的变量起名字用I/O地址可以直接映射到符号名上比如把I0.0定义为“急停按钮”程序里就直接用这个符号名。但变量表只负责“起名”它本身不负责“存储空间”的组织底层面对的还是I/O地址和M存储区。数据块不一样DB是在用户程序里真正划分出的一块独立数据存储区有完整的结构定义能定义数组、结构体、UDT还能设置保持性、初始值它是实体数据容器。初学者最常犯的毛病就是在PLC变量表里定义了一大堆中间变量比如各种计算中间值、报警标志、计时累计值用M区一片一片地分配。M区本身存储空间有限没有结构管理程序大了以后根本没法看清楚哪些M地址被哪个功能占用。而数据块的优势在于结构清晰、按逻辑划分。举个例子报警管理你在变量表里定义“报警1”“报警2”看着能凑合用但你在DB里定义一个“报警数据结构”包含报警代码、报警文本索引、触发时间、确认标志还能直接生成数组管理一百条报警就轻松很多。所以我的建议是凡是和设备逻辑紧密相关的中间量尽量放进FB的背景DB或设备的UDT型DB里M区只放那些必须用绝对地址的外部接口类东西。2. 优化访问和标准访问很多人建块时根本不看这个选项坑全在后期2.1 优化访问是什么逻辑为什么博途默认给你勾上在TIA Portal里新建S7-1200数据块时创建对话框里默认会勾选一个“优化的块访问”很多初学者直接点了确定根本不知道这个选项会带来什么后果。优化访问数据块的本质是块里的变量不再绑定固定的绝对地址PLC内部使用一种符号寻址机制来管理这些数据外部程序用符号名访问变量。优化DB是S7-1200和S7-1500的默认选项也是西门子推荐的用法。这个“不分配地址”的设计最大的好处是数据布局由系统自动优化。比如类Bool型变量标准方式每个Bool占用一个位地址但系统在处理时可能按字节对齐优化访问则能把多个Bool紧凑地打包进一个字节节省存储空间。另一个好处是修改DB里的变量声明时系统可以自动调整内部布局不会像标准DB那样因为改了变量个数和类型导致后面的偏移地址全部错位。S7-1200的工作存储器本来就有限用优化访问在空间利用上的优势是很明显的。不过优化访问也有让很多人难受的地方变量没有“绝对地址”在程序里如果非要看到类似DB1.DBX0.0这种硬地址根本看不到HMI或者上位机组态时要访问DB变量也得按符号名来连接。有些老的第三方通讯协议比如某些设备要你直接填写数据区偏移地址读写PLC数据优化DB就玩不转了。另外仿真调试时有些老工程师习惯在变量表里监控具体地址优化DB会让他们觉得“不踏实”。2.2 哪些场景必须关掉优化访问哪些场景建议保持强制要标准访问的场景主要有以下几类。一是老程序移植从S7-300/400迁移过来的DB程序里大量用了绝对地址访问比如DB1.DBW20、DB1.DBD24这种情况下如果新建DB时不勾选标准访问源代码里的地址访问全部失效。二是某些通讯协议或第三方设备需要直接按偏移地址读写PLC存储区常见的如MODBUS TCP通信从站数据区映射到DB时如果使用功能码需要明确访问的数据地址标准访问可以方便地按绝对地址搬运数据。三是S7-1200与S7-200 SMART通过S7协议通信时如果对方需要按DB编号和偏移量读数据标准DB更容易配合。非必要不建议主动取消优化访问。优化访问对存储空间的利用率更高访问指令生成也更精简整体性能只会更好而不是更差。这里给一个稳妥的做法除非你确认某个DB要被外部系统按绝对地址访问否则新建DB一律保留默认的优化访问。HMI那边用符号寻址连接变量在TIA Portal里组态非常方便不存在兼容性问题。真的碰到必须标准访问的DB就单独建一个“通信专用DB”保持标准访问业务数据则继续用优化DB两者物理分离互不拖累。2.3 数据块大小限制S7-1200到底能装多少数据S7-1200的数据块大小并不是想建多大就建多大它受两个约束单个DB的大小限制以及CPU工作存储器总容量限制。S7-1200系列CPU的单个数据块上限通常在64KB左右这个值对绝大多数设备级数据来说绰绰有余但如果你非要把整条产线数千个配方参数塞进一个DB就很可能会碰到“无法创建”或者下载时提示存储区不足。除了单个DB大小CPU的工作存储器是有限资源S7-1200不同型号差距很大低端型号工作存储器可能只有50KB左右数据块、程序块都共用这个空间。在工程中我经常遇到一个场景就是“数据块大小被限定”这其实才是设计时应该认真对待的问题。举个例子和第三方设备走Modbus TCP通讯报文数据区经常限定在几百个字以内你在PLC里建的通讯DB就不能超过这个限定的数据块大小否则对方的报文映射关系就对不上了。再比如HMI项目里变量数量可能需要几百上千个如果全部映射到PLC数据块数据块内的变量设计不合理导致块过大组态和通讯效率都会下降。所以热词里讲“优化、限定数据块大小”落到西门子1200上就是一句话在设计阶段就要有意识地把数据块做小、做精而不是等写满了再回头拆。关于单块大小上限这里做个整理方便大家心里有数项目典型限制值说明S7-1200单个DB大小约64KB与CPU型号有关超出会报错需拆分S7-1200工作存储器视CPU型号而定低端约50KB高端可达几MBDB、FB、FC、OB共享保持性存储区一般几KB到几十KB掉电保持变量占用的空间标准DB绝对寻址范围受字偏移位数限制偏移地址不能超过上限需要特别提醒的是这些数值以最新的TIA Portal软件中硬件组态显示为准不同固件版本之间可能有一些微调。但结论不变千万别在设计时留一个“反正内存很大”的心态合理规划才是正道。3. 实操从UDT到DB把一台设备的数据块建得明明白白3.1 先定义UDT别让设备数据块变成一盘散沙我接手过很多项目最大的痛点不是程序复杂而是设备数据块里变量命名乱到没法看。所以现在带项目我强制要求先规划UDT再建DB。UDT的全称是User Defined Type用户自定义数据类型它本质上就是你自己定义的一种数据结构。比如要管理一台变频器我先在TIA Portal的“PLC数据类型”里新建一个“UDT_变频器”类型然后往里面加字段TYPE UDT_变频器 VERSION : 0.1 STRUCT 启动命令 : Bool; 停止命令 : Bool; 故障复位 : Bool; 本地远程 : Bool; 当前频率 : Real; 设定频率 : Real; 输出电流 : Real; 运行状态 : Bool; 故障代码 : Word; 累计运行时间 : DInt; END_STRUCT END_TYPE这段乍一看像STL代码其实TIA门户里可以直接用SCL语言定义类型。定义完UDT后它就成了一个“模板”后面无论建多少台变频器的DB都基于这个模板实例化。这样做的好处非常明显第一所有设备的变量结构完全一致HMI做画面时复制粘贴变量表也不会错位第二程序里写FB时直接以这个UDT作为输入输出参数接口清晰第三后期在UDT里统一加一个字段比如“保养到期标志”所有基于该UDT的DB都会自动多出这个字段不用一处处手动添加。3.2 在博途里一步一步创建基于UDT的数据块实际操作步骤我以前演示过很多次这里再拆一遍。打开TIA Portal在PLC项目树的“程序块”下右键选择“添加新块”然后在弹出的对话框里选择“DB”名称填“DB_变频器”类型选“全局DB”注意看一下“数据块访问”选项如果后续不需要按绝对地址访问保持“优化访问”默认即可。创建好后在DB编辑器里定义变量最方便的做法不是逐个添加变量而是直接输入UDT类型。具体来说在变量声明表里新增一行名称写“变频器1”数据类型填“UDT_变频器”回车后你会发现这个变量自动展开了UDT里的所有字段。如果你有十台变频器只需要在DB里建十个这种类型的变量分别是“变频器1”到“变频器10”所有的内部字段全部自动带出来一台设备一个结构清晰的数据区。这个过程中有几个细节要注意。一是UDT文件本身要提前编译好否则DB里引用不了二是通过UDT实例化出来的变量在DB中的字节偏移是由系统自动安排的你不需要也不应该去手动干预三是如果后续改动了UDT的结构所有引用它的DB都会出现“需要重新编译”的提示这时直接右键程序块选择“编译”不要忽略否则下载后可能出现数据错乱。我踩过一次“改了UDT没编译就下载、老设备DB结构被覆盖”的坑从那以后任何块结构的修改我都会先编译再下载这个习惯真的能救大命。3.3 在程序里访问DB变量符号寻址和绝对寻址该怎么写创建好DB下一步就是怎么在程序里访问。优化访问DB只能用符号寻址在SCL或LAD里直接输入“DB_变频器”.变频器1.启动命令这种完整的符号路径。写LAD时可以直接拖拽DB变量到触点或线圈上也可以直接在指令里输入表达式。SCL里的典型写法大概是DB_变频器.变频器1.启动命令 : TRUE; IF DB_变频器.变频器1.当前频率 DB_变频器.变频器1.设定频率 THEN HMI_报警区.频率超限 : TRUE; END_IF;注意S7-1200里DB符号名的引用需要加双引号这和S7-300/400不太一样从老平台转过来的工程师初期很容易漏掉引号导致编译报错。如果你那个DB是标准访问也可以直接按绝对地址访问比如“DB_变频器”.DBX0.0这类写法但真的不推荐在业务程序里到处写这种硬地址一点好处没有纯粹增加阅读成本。3.4 设置保持性和初始值数据块掉电以后的行为由这里决定数据块里的变量还有一个重要属性就是保持性Retentivity。S7-1200在断电再上电后默认情况下普通DB变量会恢复为初始值也就是你在DB声明时填写的数值但你可以给某些变量勾选“保持性”让断电上电后依然保留断电前的值。这个功能对累计运行时间、计数器、配方当前参数这类数据非常关键否则设备一断电重新启动所有运行记录全部清零现场操作员第一个找的就是你。在TIA Portal里设置保持性很简单在DB编辑器底部有一个“保持性”选项卡在里面勾选需要保持的变量就行。不过要留意保持性变量是有代价的它会占用CPU的保持性存储区这个存储区是有限资源。S7-1200的保持性存储区容量不算大所以不要让所有数据保持应该只保持那些真正需要掉电保存的数据比如设备运行时间、最后一批次的生产计数而把临时计算中间量设为非保持。另外下载包含保持性修改的数据块时同样可能要求CPU停机或重新初始化部分存储区这个在下载对话框里会有提示建议量产调试前就把保持性规划好避免调试后期频繁因改保持性而整机停机。4. 数据块做小的优化手法一个老工程师的经验取舍4.1 先想清楚“谁在消费这个DB”再决定怎么设计很多人在建数据块之前根本不考虑后面谁会来访问这个DB结果就是变量想加就加块越来越大最后把自己坑了。我的经验是开工之前先列一张“数据消费者”的清单HMI需要显示哪些变量MES/SCADA上位机要读哪些数据程序内部哪些FB要访问这个DB第三方通信要映射哪些区域把这些需求列出来再倒推出来DB里该有哪些结构这样建出来的DB才叫“按需设计”而不是“想到哪写到哪”。这里说说通讯DB的优化。S7-1200支持Modbus TCP、S7通信、PROFINET等很多方式每种方式的报文长度都有限制。比如Modbus TCP的一个保持寄存器区的映射受到PDU大小的约束一次最多传输约125个字。如果你的通讯DB设计成一个大数组包含了所有数据而实际上面位机一次只读个别字就会造成带宽浪费甚至某些场景直接超出限定数据块大小。建议通讯DB和业务DB分离业务DB按设备结构存放完整数据通讯DB只建一个定长的小数组程序里用MOVE指令把需要上报的数据从业务DB搬运到通讯DB这样既安全又高效。4.2 数据类型选择和数据对齐细节决定空间能省多少S7-1200处理数据时存在“对齐”的规则简单说就是一个Real类型的变量通常占用4个字节一个DInt占用4个字节Bool类型虽然只占1位但它往往也落在字节边界上。如果结构里一会儿Bool一会儿Real一会儿Word乱排列系统会自动填充空洞导致空间浪费。优化访问模式下系统会自己优化布局但你在UDT设计时还是要有意识地按类型分组排列比如把所有Bool放前面再放Word、Int、Real这样即使系统自动布局也能更紧凑。数据类型的选择同样影响数据块大小。能放Bool的不要放Byte能放Int的不要放DInt能不放String就坚决不要用String。字符串类型在S7-1200里非常消耗空间一个String[50]默认约占52字节如果你在设备结构里放了十几个字符串字段整个DB会迅速膨胀。实际项目中可以用一个整型“文本索引”代替字符串HMI那边负责根据索引查找显示文本PLC这边只存数值数据库大小一下子就降下来了。我见过一个项目只是把所有字符串字段改成索引类型DB大小直接缩到原来的三分之一。4.3 “限定数据块大小”的真实工程场景通讯协议和固件限制热词里提到限定数据块大小这个在工程里是真实存在且常见的。第一个场景就是前面说的通讯协议限制比如S7-1200作为Modbus服务器时客户端如果只按功能码03读取某些保持寄存器PLC侧数据块就要设计成对应的映射区域大小不能超过客户端请求的报文范围。第二个场景是S7-1200与S7-1500或其他控制器做S7通信读取DB块时对方CPU资源有限大数据块的频繁读写会影响总线周期所以数据块要尽量精炼。第三个场景是CPU固件版本和存储器上限低端1200CPU的工作存储器几万字节级别你建两个大数组DB可能就满了不得不分拆或升级CPU。优化做法是什么一是把历史趋势数据移到HMI或上位机存档PLC只保留短时缓存不要试图在PLC里存一堆历史趋势。二是公共变量尽量数组化比如有20台电机每台有10个状态位不要建成200个离散变量而是定义“电机状态数组[20]”每个元素是一个包含10个Bool的结构体这样空间和代码的维护成本都大幅下降。三是定期做块检查右键数据块查看实际大小对接近上限的块主动拆分成多个按功能划分的小块别等报错了才发现。4.4 DB的版本管理改DB结构是最容易出事的操作最后说一个没有代码但极其重要的优化习惯DB的修改尤其是结构修改在已投运设备上必须当作高危操作。修改DB结构后如果直接点击“下载”系统会提示需要初始化存储区这会导致数据块中的运行数据重置设备就得重新调试。处理这类情况的专业做法是提前把DB里的关键数据通过“上传”指令备份或者在修改前把运行状态数据保存到另一个备份DB中修改下载后再从备份DB恢复。另外TIA Portal支持“离线/在线比较”下载前可以看到DB的差异特别是结构变化的部分。养成改DB之前先看比较报告的习惯能少挨不少骂。5. 数据块使用中的常见问题与排查实录5.1 修改DB结构后下载导致停机和数据丢失这是最常被问到的问题现象是在程序里给某个DB加了一个变量下载后CPU从RUN变成STOP或者设备重新上电后所有数据都变成初始值了。原因很好理解DB结构变化意味着原来的数据布局整体变了系统必须把DB重新初始化这个过程要求CPU停机处理。尤其是标准访问DB只要变量数量或类型调整后面所有变量的偏移地址全部发生变化情况更严重。我的处理流程是在修改DB前先用编程软件把DB的在线值导出来记录所有关键变量的当前值然后进行结构修改、编译、下载下载后把关键值写回去。项目允许情况下尽量选择设备计划的停产窗口来做这种操作不要在生产运行时间在线改DB。对于那些必须支持热修改的场合建议把容易变化的参数设计成独立DB块单独下载一个小DB的修改相对不容易影响CPU整机运行状态。5.2 变量访问时报错“地址越界”或“无法访问”优化DB一般不太容易出现地址越界因为系统按符号管理但标准DB或者通过指针寻址时就很容易报“区域长度错误”或“访问非法”。常见原因包括编程时拖拽的地址超出了DB定义的范围比如DB实际只有10个字节你硬访问DBW20或者UDT修改后没重新编译程序里按旧结构访问新DB数据长度对不上导致指针越过块边界。排查这种问题用TIA Portal的在线监控直接看是哪个指令报错最快。如果在线状态下某个访问DB的指令被红色标记首先检查地址是否在DB范围内其次检查UDT是否编译一致还有就是要看看自己是不是把两个不同的DB编号搞混了。我之前接手过一个人家调试了半年的项目发现程序里到处都是DB1.DBX200这种访问而实际的DB1只有100字节大概率是编译器没拦下来运行时偶尔报错这类情况只有把程序里的绝对地址访问全部换成符号访问或者重新规划数据块位置才能真正解决。5.3 保持性设置不生效断电后数据还是丢了有人问我DB变量明明勾了保持性为什么断电再上电数据还是归零这个问题八成是出在“下载”操作本身。如果修改保持性设置后直接下载数据块系统会提示该操作可能导致DB被重新初始化一旦点了“初始化”即使后面断电保持属性生效当时的数据也已经被清零了。正确的验证方法是在线情况下打开DB监控修改变量值然后将CPU断电再上电之后再去DB监控里看数值是否保持住了而不是通过下载过程去验证。另外一个容易被忽略的点是S7-1200的保持性存储区是有限资源如果勾选的保持变量总大小超过了CPU的保持性存储区容量编译时可能不会报错但实际运行时有的变量无法保持表现就是“有的变量能保持、有的不能”。遇到这种情况要么减少保持变量个数要么升级到具有更大保持性存储区的CPU型号。项目设计阶段就把保持性预算规划清楚后面就不会为这种问题抓狂。5.4 数据块在线监控正常但程序逻辑不认说一下数据块在线值和程序实际值不一致的问题。当你在TIA Portal里打开DB在线监控时看到某个变量值明明是100但程序里IF判断却不成立很有可能你监控的是离线值或者在线值在监控画面刷新之前已经发生了变化。当然更隐蔽的原因是程序里有多个地方对这个变量执行了写操作某个FB在别的周期里把它覆盖了你监控时刚好看到的是另一次写入后的结果。排这种问题最直接的办法是用交叉引用右键变量选择“交叉引用列表”看看程序里到底有哪几个地方读写这个变量同时再用“监控表”添加该变量设置触发条件看它在一个扫描周期内的变化轨迹。数据块在实际项目里好像是个“地基性”的东西不起眼但天天都在用前期设计得越好后期调试越省心。我在实施设备数据块划分的时候始终坚持“一个设备一个UDT型DB、通讯独立DB、公共数据单独DB”的原则项目交付后客户反馈维护起来特别顺手。就算你手头的项目小也建议从第一个DB开始就保持良好的组织习惯这些经验都是踩过坑换来的照抄能少走不少弯路。
返回列表