三菱PLC ST语言编程实战:从基础语法到CRC16校验实现

发布时间:2026/7/29 7:04:01

三菱PLC ST语言编程实战:从基础语法到CRC16校验实现 1. 从梯形图到结构化文本为什么我们需要ST语言如果你在三菱PLC的圈子里待过一段时间从早期的FX系列玩到现在的iQ-R、iQ-F手里用的编程软件从GX Developer换成了GX Works2或GX Works3那你大概率经历过一个编程思维的转变。最开始我们习惯用梯形图LD因为它直观像电路图继电器怎么吸合、线圈怎么得电一目了然。处理简单的起保停、顺序控制梯形图游刃有余。但当你开始接触更复杂的项目比如需要处理大量数据运算、配方管理、复杂的流程控制或者需要编写一个可复用的功能块时你就会发现用梯形图画起来会变得异常臃肿和低效。画几百个甚至上千个梯级找一根线的去向都像在迷宫里寻宝。这时候ST语言Structured Text结构化文本的价值就凸显出来了。它本质上是一种高级的、类似于Pascal或C的文本编程语言被引入到IEC 61131-3标准中成为了PLC编程的五大语言之一。在GX Works2中ST语言不再是一个陌生的选项而是处理复杂逻辑和算法的利器。我最初接触ST是因为一个简单的需求客户需要根据几个传感器的模拟量输入实时计算一个产品的质量系数这个计算公式涉及乘方、开方、三角函数和一堆条件判断。如果用梯形图实现我需要调用一堆函数块用中间变量倒来倒去逻辑支离破碎。而用ST我只需要十几行清晰明了的代码像写数学公式一样直接表达出来可读性和维护性瞬间提升了好几个档次。所以ST语言的核心价值在于它填补了传统梯形图在复杂数据处理、算法实现和结构化编程方面的短板。它让PLC程序员能够以更接近计算机软件开发的思维来组织逻辑特别适合数学运算、字符串处理、数组操作、循环和条件分支复杂的场景。对于从计算机或嵌入式背景转过来的工程师ST语言更是几乎没有学习门槛能让他们快速上手PLC逻辑开发。接下来我们就深入GX Works2看看如何开启你的ST编程之旅。2. GX Works2中的ST编程环境搭建与核心语法要素在GX Works2中ST语言并非孤立存在它可以和梯形图、顺序功能图SFC、功能块图FBD等语言混合编程这是IEC 61131-3标准的强大之处。你可以在一个程序段POU程序组织单元里使用ST在另一个程序段里使用梯形图它们通过全局变量或接口变量进行数据交互。2.1 创建你的第一个ST程序段打开GX Works2创建一个新工程选择对应的PLC型号例如FX5U。在工程导航树的“程序”下右键点击“程序本体”选择“新建数据”。在弹窗中数据类型选择“程序语言”然后你就能看到ST的选项了。给它起个名字比如“MainLogic_ST”点击确定一个空白的ST编辑器窗口就会打开。这个编辑器和我们常用的代码编辑器很像有语法高亮、自动缩进和基本的错误提示。这里有一个非常重要的概念在ST中所有的语句都以分号;结束这和C语言类似是很多初学者容易忘记的地方。2.2 ST语言的核心语法构件ST语言的语法并不复杂它由以下几个核心构件组成1. 变量与数据类型ST是强类型语言所有变量必须先声明后使用。在GX Works2的ST编辑器中你通常会在程序开头或专门的“局部变量声明区”进行声明。三菱PLC的数据类型非常丰富基本类型BOOL位如X0, M0INT/DINT16位/32位整数REAL浮点数STRING字符串。衍生类型ARRAY数组如ARRAY[1..10] OF INT表示10个整数的数组。STRUCT结构体可以将不同类型的数据打包。直接地址你也可以直接使用PLC的软元件地址如D100,M100但在结构化编程中更推荐使用有意义的变量名然后通过软件设置关联到实际地址。声明示例VAR bStartButton AT %MX0: BOOL; // 将bStartButton变量关联到输入X0 iCounter: INT; rTemperature: REAL; arrData: ARRAY[1..5] OF DINT; END_VAR2. 赋值语句这是最常用的语句使用:运算符。iCounter : 100; rTemperature : rTemperature 1.5; bMotorRunning : TRUE; // BOOL类型赋值3. 条件判断IF...ELSIF...ELSE...END_IF和大多数语言一样用于分支逻辑。IF bStartButton AND NOT bFault THEN bMotorRunning : TRUE; iCounter : 0; ELSIF bStopButton THEN bMotorRunning : FALSE; ELSE // 保持原状态 END_IF;4. 循环语句FOR循环用于已知次数的循环。FOR i : 1 TO 10 BY 1 DO arrData[i] : i * 2; END_FOR;WHILE循环用于条件满足时的循环。WHILE iCounter 100 DO iCounter : iCounter 1; // 注意必须有能改变循环条件的语句否则是死循环 END_WHILE;5. 函数与功能块调用ST可以方便地调用系统内置函数和用户自定义的功能块FB。函数有返回值如数学函数SIN(rAngle),SQRT(rValue)类型转换函数INT_TO_REAL(iValue)。rResult : SIN(rAngle) * 100.0;功能块具有内部状态每次调用可能产生不同输出如定时器TON、计数器CTU。在ST中调用功能块需要先实例化声明一个该FB的变量然后通过实例名调用。VAR tonDelay: TON; // 声明一个接通延时定时器实例 END_VAR tonDelay(IN:bStart, PT:T#5S); // 调用设置参数 bTimeOut : tonDelay.Q; // 获取输出注意GX Works2的ST语言是IEC 61131-3标准的一个子集并有三菱自己的扩展。在编写复杂运算时务必在软件帮助中查询特定函数或运算符的兼容性避免使用标准中定义但GX Works2未实现的语法。3. 实战用ST语言实现一个复杂的CRC16校验功能网络热词中提到了“三菱st语言crc16计算”这确实是一个ST语言大显身手的典型场景。CRC循环冗余校验在通信中广泛应用例如Modbus RTU协议。用梯形图实现CRC计算需要大量的位操作和循环逻辑极其繁琐。而用ST语言我们可以清晰地用算法逻辑来实现。假设我们需要为一段数据存储在数组arrTxData中计算Modbus RTU标准的CRC16校验码多项式0xA001。下面我们一步步用ST语言实现。3.1 算法理解与变量声明首先我们需要明白CRC16计算的核心是一个对数据每个字节进行位操作的循环过程。我们声明必要的变量VAR // 假设要计算CRC的数据包共6个字节 arrTxData: ARRAY[1..6] OF BYTE : [16#01, 16#03, 16#00, 16#00, 16#00, 16#01]; uiCRCValue: WORD : 16#FFFF; // CRC初始值 iDataIndex: INT; // 数据索引 iBitIndex: INT; // 位索引 bBit: BOOL; // 临时位变量 END_VAR3.2 ST语言实现CRC16计算逻辑我们将计算过程封装在一个循环中。注意ST语言中对于字节和位的操作非常直接。// CRC16计算主循环 FOR iDataIndex : 1 TO 6 DO // 遍历数据数组的每个字节 uiCRCValue : uiCRCValue XOR WORD(arrTxData[iDataIndex]); // 字节与CRC低字节异或 FOR iBitIndex : 1 TO 8 DO // 对每个字节的8位进行处理 bBit : BOOL(uiCRCValue.0); // 取出CRC最低位 (LSB) uiCRCValue : SHR(uiCRCValue, 1); // CRC右移一位 IF bBit THEN uiCRCValue : uiCRCValue XOR 16#A001; // 如果移出位为1则与多项式异或 END_IF; END_FOR; END_FOR; // 最终uiCRCValue中存储的就是CRC16校验码 // 注意Modbus RTU协议要求先发送低字节再发送高字节 wCalculatedCRC : uiCRCValue; // 假设wCalculatedCRC是一个WORD型变量用于存储结果代码解读与实操心得类型转换WORD(arrTxData[iDataIndex])是将BYTE类型显式转换为WORD类型以便进行异或运算。在ST中注意数据类型匹配避免隐式转换带来的意外。位访问uiCRCValue.0是直接访问uiCRCValue这个WORD变量的第0位最低位。这是三菱ST语言的一个便捷特性。其他品牌的PLC可能需要通过位与AND和移位操作来实现。移位函数SHR是逻辑右移函数。这里每次右移一位。多项式16#A001是Modbus CRC16的多项式0xA001的十六进制表示。这是CRC16-Modbus的标准值。踩坑提醒我最初实现时犯过一个错误在内层位循环结束后没有正确地进行下一次字节的异或。务必确认你的数据遍历逻辑和位处理逻辑是严格嵌套的。另一个常见问题是字节顺序。计算出的CRC值在放入通信帧时需要按照协议要求调整高低字节顺序Modbus RTU是先低后高。上述代码计算出的uiCRCValue其低8位是uiCRCValue.1或通过BYTE(uiCRCValue)获取高8位是BYTE(SHR(uiCRCValue, 8))。如果顺序弄反通信对方会校验失败。3.3 将CRC功能封装为功能块FB一个更工程化的做法是将上述逻辑封装成一个可重用的功能块FB比如FB_CRC16_Modbus。这样在程序中任何需要计算CRC的地方只需要实例化并调用这个FB即可输入数据数组和长度输出CRC值代码整洁且易于维护。在GX Works2中创建ST语言的功能块非常方便这体现了ST语言在模块化设计上的优势。4. ST语言中的高级功能与混合编程技巧掌握了基础语法和实战案例后我们可以探索ST语言更强大的能力以及如何与其他语言协同工作。4.1 使用CASE语句处理多路分支当有多个确定的值需要判断时CASE语句比一连串的IF...ELSIF更清晰。CASE iMode OF 1: rSetSpeed : 10.0; bPump1 : TRUE; 2: rSetSpeed : 20.0; bPump1 : TRUE; bPump2 : TRUE; 3: rSetSpeed : 50.0; // ...其他操作 ELSE // 默认情况处理非法值 bFault : TRUE; END_CASE;4.2 结构体STRUCT组织复杂数据对于一台设备的多组参数使用结构体管理比分散的变量要高效得多。TYPE ST_Recipe : STRUCT rTemperature_SET: REAL; rPressure_SET: REAL; iTime_SET: INT; bEnable: BOOL; END_STRUCT END_TYPE VAR stCurrentRecipe: ST_Recipe; stBackupRecipe: ST_Recipe; END_VAR // 使用 stCurrentRecipe.rTemperature_SET : 150.5; IF stBackupRecipe.bEnable THEN stCurrentRecipe : stBackupRecipe; // 整体复制 END_IF;4.3 ST与梯形图LD的混合编程与交互这是GX Works2的精髓。你可以在一个FB或程序里部分逻辑用ST写比如复杂的计算部分用梯形图画比如简单的联锁和启停。它们通过变量无缝交互。场景一个PID温度控制回路。PID算法本身用ST语言实现因为它涉及浮点运算和条件判断。而设备的启动、停止、报警复位等安全联锁逻辑用梯形图实现更直观。操作在同一个POU内你可以插入多个“段”Section。为一段选择“结构化文本ST”为另一段选择“梯形图LD”。在ST段中你声明并计算一个实型变量rPID_Output。在梯形图段中你可以直接用一个线圈或比较指令来使用这个rPID_Output变量控制一个模拟量输出模块或作为其他逻辑的输入。交互的关键全局变量或FB的输入输出变量。确保在ST中修改的变量在梯形图中能够正确访问。在GX Works2的变量声明表中可以清晰地管理这些变量的作用域局部、全局。4.4 利用EXP等数学函数进行工程计算热词中提到了“exp在st语言”EXP是指数函数e^x。在ST中调用它非常简单用于需要指数计算的模型如某些化学反应速率、生长模型等。VAR rGrowthRate: REAL; rTime: REAL : 2.0; rCoefficient: REAL : 0.5; END_VAR // 计算例如生长速率 e^(系数 * 时间) rGrowthRate : EXP(rCoefficient * rTime);除了EXPGX Works2的ST语言库通常还包含LN自然对数、LOG常用对数、SIN、COS、TAN等全套数学函数使得实现复杂的控制算法成为可能。5. 学习路径与工程实践中的注意事项对于想系统学习三菱PLC ST语言的朋友光靠官方手册可能有些枯燥。结合我的经验给出以下建议5.1 学习资源与推荐路径官方文档是基石三菱电机官网提供的GX Works2操作手册、编程手册特别是结构化文本篇是必须精读的。里面详细规定了语法、函数库和软件操作。实践项目驱动不要只看不练。从一个小目标开始比如把之前用梯形图写的一个繁琐的报警处理程序用ST语言重写。体会两者在逻辑表达上的差异。参考热词提及的书籍虽然无法推荐具体书籍但可以告诉你筛选方法。寻找书名中包含“IEC 61131-3”、“结构化文本ST”、“PLC高级编程”等关键词的书籍。优先选择那些有大量实际案例和代码片段并且注明适用于多品牌PLC如西门子SCL、倍福ST、三菱ST的教材因为ST语言的核心语法是相通的这类书籍通常讲解得更透彻。利用网络社区和案例积极参与相关的技术论坛查看别人分享的ST语言代码片段特别是针对特定功能如PID、通信协议解析、数据队列管理的实现。理解别人的思路比复制代码更重要。5.2 工程应用中的关键陷阱与调试技巧陷阱1扫描周期与执行顺序ST语言编写的程序段其执行顺序由它在POU中的位置决定通常从上到下。你需要非常清楚PLC的扫描周期输入采样 - 程序执行 - 输出刷新。在ST中如果一个变量在同一扫描周期内被多次赋值只有最后一次赋值生效。这与梯形图的“电流”流动概念不同需要从“顺序执行”的软件思维去理解。调试技巧善用GX Works2的在线监视和断点调试功能。在ST编辑器中你可以设置断点让PLC运行到指定行暂停然后查看此时所有变量的值这对于排查复杂的逻辑错误和算法错误至关重要。陷阱2变量初始化与保持性在ST中声明的局部变量默认每个扫描周期都会重新初始化除非你声明为RETAIN类型或使用VAR_GLOBAL RETAIN。如果你需要一个在PLC断电再上电后能保持值的变量比如累计产量必须将其设置为保持型变量并确认PLC的硬件支持电池或非易失性存储器。VAR RETAIN iTotalCount: DINT : 0; // 保持型变量初始值为0 END_VAR陷阱3数组越界与类型溢出这是ST编程中最常见的运行时错误之一。访问数组时索引值必须在声明范围内。进行数学运算时要注意数据类型的范围如INT的范围是-32768~32767。一个超出范围的赋值可能导致不可预知的行为。防御性编程在访问数组前增加索引有效性检查。对于可能溢出的计算考虑使用范围更大的数据类型如用DINT代替INT或者在计算前进行限幅判断。陷阱4ST与LD混编时的变量竞争当ST段和梯形图段同时读写同一个变量时如果逻辑设计不当可能会产生“竞争条件”。由于PLC是顺序扫描后执行的段会覆盖先执行段的结果。因此在混合编程时最好明确数据的流向避免双向读写同一个变量。通常让ST段负责“计算”将结果写入一组变量让梯形图段负责“控制”读取这组变量并产生最终输出。从我个人的项目经验来看ST语言的学习曲线初期可能比梯形图陡峭但一旦掌握它会极大地提升你处理复杂控制任务的效率和代码质量。它迫使你以更结构化的方式思考问题这本身就是一种宝贵的技能提升。在GX Works2这个平台上大胆地将ST语言用起来从一个小功能块开始你会发现PLC编程的世界原来可以如此不同。

相关新闻