news 2026/9/24 10:46:44

汇川H5U PLC ST语言编程入门:7步从梯形图到结构化文本

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
汇川H5U PLC ST语言编程入门:7步从梯形图到结构化文本

先交代一个真实的场景:去年我在一条小型包装线上,把一套原本用梯形图堆了三天的控制逻辑,改用汇川H5U PLC的ST语言重写,整个逻辑部分从600多行缩短到200多行,一个刚入行一年的电气工程师拿过去,两天就能看懂并改参数。这件事让我彻底认了一件事——汇川H5U做中型设备、多轴运动和数据处理时,ST语言不是"要不要学"的问题,而是"迟早要学"的问题。

这篇内容主要面向两类人:一类是之前一直用梯形图、想转ST但找不到完整路径的电气工程师;另一类是已经接触过ST、但在H5U上还没有形成系统写法的工控人。我整理了7个步骤,从建工程、写变量、写语句、写流程、写循环、封装功能块,一直到在线调试和报警排查,每一步都给出可以直接复制到AutoShop里跑的代码片段,以及我实际踩过的一些坑。学完这7步,你写H5U的ST程序就能从"照着例子改"过渡到"按自己的思路搭程序"。

1. 为什么从梯形图转向ST语言:H5U的定位与ST的用武之地

1.1 H5U到底是一台什么样的PLC

汇川H5U系列是汇川面向中高端小型设备市场推出的中型PLC,官方定位是"中小型运动控制与逻辑控制一体化"。它和旧款H1U、H2U这类传统小型机最大的区别,是内核采用了基于CODESYS V3的运行时环境,支持IEC 61131-3标准的全部五种编程语言:LD(梯形图)、FBD(功能块图)、ST(结构化文本)、SFC(顺序功能图)、IL(指令表)。换句话说,H5U不是一台"能写ST的老式PLC",而是一台真正为复杂逻辑、数据处理和运动控制准备的平台。

我最早用的是H5U-1614MTD这个型号,16点输入、14点晶体管输出,带2路EtherCAT总线,最大支持8个从站轴。说实话,如果你只是拿它替代H1U做继电器逻辑,其实有点浪费。H5U真正发力的场景是:需要EtherCAT伺服、需要模拟量算法处理、需要把重复设备逻辑做成标准化功能块、需要和上位机或HMI做大量数据交互。这些场景里,梯形图不是不能做,是做得非常痛苦——一段平均值滤波梯形图要写十几行网段,ST只需要三行。

1.2 ST语言和梯形图的本质差异

很多老师傅对ST的第一反应是"像C语言,离PLC远了,不安全"。这个我理解,但说实话,这种想法更多是习惯问题。

梯形图的本质是"电气回路思维":每个网络就是一条从左母线到右母线的"虚拟电路",程序执行顺序就是网络从上到下、从左到右的扫描。这种思维的优势在于直观,一个懂继电器电路的人就能看懂,排查现场问题时可以顺回路找。但它的劣势也很明显——项目一旦超过300个网络,整个程序的可读性会急剧下降,改一个流程可能要翻好几屏,而且很难做数据的批量运算。

ST语言的本质是"脚本执行思维":它按IEC 61131-3标准定义了一套完整的语句和操作符,包括赋值、条件分支、循环、函数和功能块调用,语法风格接近Pascal。你用ST写程序,实际上是在用文字描述控制逻辑。好处有四个:

  • 同样是做10个模拟量的平均值滤波,ST的FOR循环能在10行内解决,梯形图可能要50行以上
  • 逻辑结构清晰,注释写好了,后续维护的人不需要逐行看梯形图网段
  • 同样的算法代码可以在不同PLC品牌之间跨平台复用,因为IEC 61131-3标准是通用的
  • 函数和功能块的封装能力,能让设备程序真正实现"一次封装、到处调用"

以我个人的使用经验来说,H5U上ST和LD的最佳配比不是非此即彼,而是一个设备程序里,逻辑互锁、安全回路这些电气工程师最关心的部分可以用LD保留,而所有涉及数据处理、流程状态机、批量运算的部分全部交给ST。这也是下面7步里贯穿始终的思路。

1.3 7步总览,先建立整体框架

在进入具体操作之前,我先给出一张整体的步骤表,方便你心里有个地图。后面每个章节对应其中一到两步,逐步展开。

步骤核心内容对应章节
第1步H5U开发环境搭建与新建ST工程第2节
第2步ST变量声明与数据类型基础第2节
第3步ST运算与赋值语句,写最小编程单元第3节
第4步IF / CASE条件分支,让程序认识状态第3节
第5步FOR / WHILE循环与数组批量处理第4节
第6步功能块(FB)与函数(FUN)封装复用第4节
第7步在线调试、断点监视与报警排查第5节

这7步并不是完全独立的,前面几步是语法地基,后面两步是工程化能力。你学完第5、6步之后,回头看前4步会更有感觉。

2. 第1-2步:从建工程到写出第一段ST程序

2.1 开发环境搭建,最容易忽略的三个细节

H5U的编程软件是AutoShop(汇川统一编程平台),软件本身可以从汇川官网下载,安装过程比较常规,一路下一步就行。但有几个细节我吃过亏,提醒一下。

第一,AutoShop版本和固件版本要对上。H5U的固件更新比较频繁,如果你用旧版AutoShop连接新出厂的H5U,软件会提示固件版本不匹配,这时不要随便点"升级固件",而是先确认你手里的固件文件是不是设备原厂版本。我遇到过现场回传设备,发现固件被上一个调试人员升过级,但程序还是旧版,导致下载时直接报错。稳妥的做法是:新建工程前先到"帮助-关于"里看AutoShop版本,再在PLC上电后用USB连接看固件版本,尽量保证二者是配套的。

第二,通信驱动的安装。AutoShop通过USB连接H5U时,Windows会识别为一个虚拟串口设备,但有时候驱动不会自动装上。如果插上USB线后设备管理器里出现黄色感叹号,去AutoShop安装目录下找驱动文件夹手动更新驱动即可。另外,如果使用以太网连接,需要把电脑IP设为和PLC同一网段,H5U默认IP一般写在机身标签上,首次连接建议直接用USB,确定IP后再切换网络。

第三,工程模板的选择。新建工程时AutoShop会让你选择PLC型号和工程模板,一定要按实际型号选,比如H5U-1614MTD就不要选成H5U-2414MTD。选错型号的后果是I/O地址映射不完整,程序下载后输入输出点对不上,轻则报警,重则误动作。这个错误在新手期特别容易犯。

2.2 ST程序的最小单元:变量声明区与代码区

打开AutoShop后,在左侧工程树里找到"程序组织单元"(POU),右键添加一个POU,语言类型选"结构化文本(ST)"。这时你会看到编辑器里默认有两块区域:上面的变量声明区和下面的代码区。

ST语言和C语言有个很大的区别:C语言可以在函数体任意位置声明变量,而ST要求在程序开头集中声明。H5U的ST变量声明区以VAR开头、END_VAR结尾,中间可以声明BOOL、INT、REAL等数据类型的变量,还能给变量赋初值。

我一般会在代码区第一行写一个程序名称注释,然后空一行再开始写逻辑。比如一个最简单的点动程序:

VAR bStart : BOOL := FALSE; bStop : BOOL := FALSE; bRun : BOOL := FALSE; nCount : INT := 0; rVolt : REAL := 0.0; END_VAR // 主逻辑:点动运行,停止优先 bRun := bStart AND NOT bStop; // 计数演示:单击一次bStart,计数加1 IF bStart AND NOT bRun THEN nCount := nCount + 1; END_IF

这段代码你直接复制到AutoShop的ST编辑器里就能编译。注意几个ST的基本规则:语句结尾用分号;,注释用//或者(* *),赋值符号是:=而不是等号=,布尔型变量的值是大写的TRUEFALSE

2.3 H5U支持的常用数据类型,选错类型会踩大坑

ST之所以比梯形图更适合数据处理,核心在于它有完整的数据类型体系。H5U的ST里常用的类型如下:

数据类型位宽取值范围示例典型用途
BOOL1位TRUE / FALSE开关量、启停状态
BYTE8位0~255小型状态码
WORD16位0~65535通讯状态字
DWORD32位0~4294967295位组合状态
INT16位-32768~32767常规整数计数
DINT32位-2147483648~2147483647大范围整数计数
REAL32位-3.4E38~3.4E38模拟量、浮点运算
STRING可变字符上位机交互文本

这里最容易被忽略的坑有两个。

第一个是INT和DINT溢出。H5U的默认整数类型在某些隐式转换时是按INT处理的,当你的计数器计数值可能超过32767时,必须显式声明为DINT。我见过一个设备,产量计数用的是INT,连续生产两个月后计数突然变成负数,就是因为溢出回绕了。这个错位很隐蔽,排查起来也费劲,一定要在声明阶段就规划好。

第二个是REAL和INT混用。ST里 INT和REAL不能直接赋值和参与运算,需要做类型转换。H5U提供了INT_TO_REALREAL_TO_INT这样的转换函数,比如:

nCount := REAL_TO_INT(rVolt * 10.0);

如果你偷懒直接写nCount := rVolt * 10.0;,编译会直接报类型错误。这其实是好事,意味着你在编译期就能发现类型问题,不会等到现场出故障再查。

2.4 I/O地址映射:H5U的软硬分离机制

H5U的ST程序里访问物理输入输出点,并不是直接写X0、Y0这样的地址,而是通过I/O映射地址。AutoShop会为每个输入点分配一个%I开头的地址,每个输出点分配一个%Q开头的地址。比如H5U-1614MTD的输入点对应%IX0.0%IX0.7%IX1.0%IX1.7,输出点对应%QX0.0%QX0.7%QX1.0%QX1.5

在ST里最好别直接用%IX0.0这种裸地址,建议在变量声明区建立软变量映射:

VAR bInStart : BOOL := FALSE; // 启动按钮映射 bInStop : BOOL := FALSE; // 停止按钮映射 bOutMotor : BOOL := FALSE; // 电机输出映射 END_VAR // 在代码区开头做地址映射 bInStart := %IX0.0; bInStop := %IX0.2; %QX0.0 := bOutMotor;

这样做的核心原因是可维护性。将来如果现场互换输入点,你只需要改映射那一行,不用改全程序的逻辑。这是标准化编程的起点,也是从"会写ST"到"写好ST"的第一道分水岭。

3. 第3-4步:ST语言的运算与流程控制,让程序学会判断

3.1 赋值、算术、逻辑与比较运算,ST的基本功

ST语言的运算体系继承了高级语言的表达能力,这是梯形图完全不具备的。H5U的ST支持以下常用操作符:

  • 赋值操作符::=
  • 算术操作符:+-*/MOD(取余)
  • 比较操作符:=(等于)、<>(不等于)、<><=>=
  • 逻辑操作符:ANDORXORNOT
  • 括号优先级:()最高,算术其次,逻辑最低

一个实际生产中的例子:现场有一个温度模拟量输入rTemp,一个压力模拟量输入rPress,当温度大于80度且压力小于2.5MPa时,需要输出报警信号。ST写出来就三行:

bAlarm := (rTemp > 80.0) AND (rPress < 2.5); %QX2.3 := bAlarm;

同样逻辑用梯形图,你要画两个比较块、一个与逻辑块、再加一个输出线圈。这不是说梯形图不能用,而是ST在可读性和效率上明显更优,尤其在模拟量比较这类场景,ST天然就是为这种表达式设计的。

3.2 IF条件分支:从单条件到多状态判断

IF语句是ST里用得最多的流程控制语句,语法结构如下:

IF 条件1 THEN // 条件1成立时的逻辑 ELSIF 条件2 THEN // 条件2成立时的逻辑 ELSE // 以上条件都不成立时的逻辑 END_IF

注意ST里是ELSIF,不是C语言的else if,少一个字母。很多从C语言迁移过来的工程师第一次写ST都会在这里拼写错误。

在H5U上我用IF语句最多的场景,是设备的手动/自动模式切换。手工模式需要按按钮直接点动,自动模式则要按固定流程走。我会把模式变量定义成nMode,然后判断:

VAR nMode : INT; // 0=停机 1=手动 2=自动 bHandStart : BOOL; bAutoStart : BOOL; bAutoStop : BOOL; bMotoRun : BOOL := FALSE; END_VAR IF nMode = 0 THEN bMotoRun := FALSE; ELSIF nMode = 1 THEN bMotoRun := bHandStart; ELSIF nMode = 2 THEN bMotoRun := bAutoStart AND NOT bAutoStop; ELSE bMotoRun := FALSE; END_IF

这种写法最大的好处是"单一出口"原则——无论什么模式下,最终只维护一个bMotoRun变量,不会出现多个输出点在程序里互相拉扯的情况。这也是我推荐在ST里尽量用"一个控制结果对应一个输出变量"的原因。

3.3 CASE分支:多状态流程的首选,告别青春版梯形图

当判断的分支数量超过三个时,IF嵌套会变得很难读,这时应该用CASE语句。CASE特别适合设备的状态机编程,比如一个自动送料设备的状态:初始化、待机、抓取、移动、放料、复位。

VAR nState : INT := 0; // 0=初始化 10=待机 20=执行中 30=异常 END_VAR CASE nState OF 0: // 初始化 IF %IX0.0 THEN nState := 10; END_IF 10: // 待机,等待启动命令 IF bStartCmd THEN nState := 20; END_IF 20: // 执行中:调用各动作 bMotoRun := TRUE; IF bFinishSignal THEN bMotoRun := FALSE; nState := 10; END_IF 30: // 异常报警 bAlarmLamp := TRUE; IF bResetCmd THEN bAlarmLamp := FALSE; nState := 10; END_IF ELSE // 兜底逻辑:任何未定义状态都回到初始化 nState := 0; END_CASE

这里要特别强调ELSE兜底分支。很多新手写CASE时只写几个具体分支,不写ELSE,一旦状态变量被干扰或者传入了未定义的数值,程序就会"卡住"——没有任何分支处理它,输出保持上一次的状态,这在设备控制里很危险。加上ELSE兜底,程序永远有退路。

3.4 定时器TON在ST里的调用方式

H5U的ST里调用定时器,并不是像梯形图那样拖一个TON块放上去,而是需要先声明一个定时器功能块实例,然后调用它。ST调用功能块的本质是"调用一个带内部记忆的代码块",用点操作符访问它的输入输出引脚。

VAR fbStartDelay : TON; // TON:通电延时定时器 bDelayDone : BOOL; END_VAR // TON输入引脚赋值 fbStartDelay(IN := %IX0.0, PT := T#5S); // 读取定时器输出:延时5秒后bDelayDone为TRUE bDelayDone := fbStartDelay.Q;

T#5S是ST语言特有的时间字面量写法,表示5秒。PT是预设时间,ET是已计时时间,Q是定时器输出。需要特别注意的是,TON实例在程序里同一时刻只能在一个POU中被调用一次,如果你在多个PRG里使用了同一个fbStartDelay实例,编译虽然能过,但运行时的结果会跟你预想的完全不同。这是新手用ST比较容易忽略的一个大坑。

4. 第5-6步:用循环和功能块把重复劳动交给PLC

4.1 FOR循环:批量处理模拟量的利器

梯形图没有真正意义上的循环语句,ST有。FOR循环的价值在H5U这类设备PLC上,最典型的应用就是模拟量数组的批量处理。

比如现场有8个温度传感器,通过8个模拟量输入通道采集原始值arrAD[0]arrAD[7],你需要把它们转换成实际的摄氏度,并求平均值和最大值。用FOR循环一行搞定转换逻辑:

VAR arrAD : ARRAY[0..7] OF INT; // 8路AD原始值 arrTemp : ARRAY[0..7] OF REAL; // 8路温度值 i : INT; rSum : REAL := 0.0; rAvg : REAL := 0.0; rMax : REAL := -999.0; END_VAR // 批量转换:AD值乘以0.1加上偏移量,模拟常见的热电偶线性换算 FOR i := 0 TO 7 DO arrTemp[i] := INT_TO_REAL(arrAD[i]) * 0.1 - 20.0; END_FOR // 求平均值和最大值 rSum := 0.0; rMax := -999.0; FOR i := 0 TO 7 DO rSum := rSum + arrTemp[i]; IF arrTemp[i] > rMax THEN rMax := arrTemp[i]; END_IF END_FOR rAvg := rSum / 8.0;

注意FOR循环的循环变量i要提前声明为INT,循环范围是0 TO 7,默认步长为1。如果要步长为2,写作FOR i := 0 TO 7 BY 2 DO。这里有一个关键习惯:FOR循环执行完之后,如果后面还要用i做边界判断,记得重新赋值,否则i会是循环结束后的值(8),而不是0,容易导致数组越界。

4.2 WHILE循环:什么时候用它,什么时候慎用

WHILE循环在PLC里不建议轻易使用,这是我在实际项目中吃过亏之后才切身体会到的。

WHILE bCondition DO // 循环体 END_WHILE

WHILE在PC编程里很常见,但PLC的程序是周期性扫描执行的,一个扫描周期内如果WHILE条件一直为TRUE,程序就会一直卡在这个循环里不出来。它的后果比FOR严重得多:FOR有明确的循环次数上限,WHILE只要条件成立就无限循环下去,这会导致PLC的扫描周期拉长,看门狗超时,整个PLC直接停机报警。

我的处理原则是:在H5U的ST里,凡是能用FOR解决的问题一律不用WHILE;如果一定要用WHILE,则必须在循环体里加上退出条件计数器,最多执行N次强制退出。下面是一个保险写法:

VAR nLoopGuard : INT := 0; bCondition : BOOL := TRUE; END_VAR nLoopGuard := 0; WHILE bCondition AND (nLoopGuard < 100) DO // 执行逻辑 nLoopGuard := nLoopGuard + 1; END_WHILE

这样即使条件一直成立,也最多循环100次,不会拖死扫描周期。

4.3 功能块(FB)与函数(FUN)的本质区别

到了这一步,ST真正拉开梯形图差距的能力才体现出来——封装。H5U的ST支持两种封装手段:FUNCTION(函数)和FUNCTION_BLOCK(功能块)。

它们的本质区别在于:函数(FUN)没有内部记忆能力,同样的输入,每次执行返回相同的结果,比如加法函数、类型转换函数;而功能块(FB)有内部静态变量,可以记忆上次执行的状态,比如定时器、计数器、状态机。判断该用FUN还是FB,就一句话:需要在两次调用之间记住信息吗?需要就用FB,不需要就用FUN。

在AutoShop里添加FUN或FB时,同样是右键POU新建,选择对应类型。一个典型的电机控制功能块可以写成这样:

FUNCTION_BLOCK FB_Motor VAR_INPUT bStart : BOOL := FALSE; // 启动命令 bStop : BOOL := FALSE; // 停止命令 bFault : BOOL := FALSE; // 故障信号 END_VAR VAR_OUTPUT bRun : BOOL := FALSE; // 运行输出 END_VAR IF bFault THEN bRun := FALSE; ELSIF bStop THEN bRun := FALSE; ELSIF bStart THEN bRun := TRUE; END_IF

这个功能块的特点是"停止优先"和"故障优先":只要故障或停止信号为TRUE,输出一定是FALSE。这在设备安全逻辑里是必须的,无论启动信号是否一直为TRUE,故障时都绝不能继续运行。

4.4 主程序里实例化功能块,同一套逻辑管十台电机

封装只是一个开始,真正体现价值的是实例化调用。比如一条设备线有8台电机,传统梯形图你就要复制8份电机启停电路,每份改一个地址,改起来费时还容易漏改。用ST功能块,你只需要在程序全局区实例化8个FB_Motor实例,然后在主PRG里分别调用:

VAR fbMotor1 : FB_Motor; fbMotor2 : FB_Motor; fbMotor3 : FB_Motor; // ... 一直到 fbMotor8 END_VAR // 主程序调用 fbMotor1(bStart := %IX0.0, bStop := %IX0.1, bFault := %IX0.2); %QX0.0 := fbMotor1.bRun; fbMotor2(bStart := %IX0.3, bStop := %IX0.4, bFault := %IX0.5); %QX0.1 := fbMotor2.bRun;

这段代码的可维护性优势是碾压性的:如果之后你发现电机启动逻辑还要加一个"前级设备就绪"条件,只需要改FB_Motor功能块内部的一行代码,8台电机的逻辑就全部更新了。这在梯形图时代,你需要在8个电路里重复修改8次。设备越多,ST封装的优势越大。

4.5 任务配置:ST代码在哪个任务里跑,决定了响应速度

封装完功能块后,有一个H5U特有的细节容易忽略——任务配置。在AutoShop工程树里找到"任务配置",默认会有一个主任务(MainTask),扫描周期可以设置,比如2ms、5ms、10ms。ST程序默认都是在主任务里执行的。

如果你有高速响应需求(比如伺服急停、编码器计数),建议把这些逻辑放到一个独立的高速任务里,周期设置为1ms或2ms,然后把普通逻辑放在主任务里。任务配置的原则是:高速任务里只放必要的、短小精悍的代码,不要放FOR循环、字符串处理这类耗时的操作,否则任务会超时,H5U会报警"任务溢出"。

另外一个容易踩的坑是:高速任务和主任务之间共享变量时要考虑扫描周期不一致的问题。同一次扫描中,主任务读到的变量值可能比高速任务晚一个周期,这在某些场合会出现"看起来莫名其妙的延迟",实际就是任务周期错位。简单处理办法是两个任务之间尽量用临时变量传值,避免耦合。

5. 第7步:综合调试,把ST程序跑出工业级的效果

5.1 在线监视:ST代码里的变量实时值怎么看

程序写完了,编译通过只是一小步,真正验证逻辑的是在线调试。H5U的AutoShop支持在线监视ST代码。下载程序后,点击"登录"按钮,PLC进入在线状态,ST编辑器里每一行的变量上都会显示当前的实时值。这是排查逻辑最直接的手段——程序有没有进到某个IF分支,一眼就能看出来。

我调试ST程序时有个固定习惯:先在变量声明区把关键变量加入"监视列表"(AutoShop里叫Watch Window)。比如模式变量nMode、当前状态nState、报警标志bAlarm,在监视列表里可以一次看到所有关键变量的实时变化,不用在密密麻麻的代码里一个个找。

需要特别注意,在线监视时的实时值是PLC的实际运行值,不是仿真值。H5U支持在线修改(在运行状态下修改程序),修改后需要点击"下载"按钮,这个操作会中断程序执行,在产线上操作时必须先确认设备安全状态,最好在设备停机时做在线修改。

5.2 断点调试与变量强制,排查"逻辑不按预期走"的利器

当程序运行结果和预期不一致,又找不到原因时,断点调试是效率最高的手段。AutoShop的ST编辑器支持设置断点,在线状态下程序执行到断点处会暂停,这时你可以查看所有变量的当前值,然后单步执行,逐步观察变量变化。

我举一个真实例子:有一次设备在自动模式下,偶尔会出现气缸误动作,但不是每次都有。梯形图时代我几乎没法查这种偶发问题,只能加辅助继电器慢慢跟。用ST后,我把怀疑的那段IF分支设置断点,然后把异常条件变量强制为TRUE/FALSE反复触发,很快就定位到是一个中间变量在上一段逻辑里被意外覆盖了。

变量强制功能也很有用。比如你想模拟"油温过高"这个故障标志为TRUE的情况,不需要真的去加热油,直接在在线监视窗口把对应变量强制为TRUE,再观察程序的反应。注意强制变量的值后,PLC程序执行到该变量的赋值语句时会被覆盖,所以强制只对"暂时没有赋值逻辑的变量"有效,这是ST调试里一个比较容易误解的点。

5.3 ST程序最常见的四类错误排查

第一类:类型不匹配。编译阶段就会报错,提示Type mismatch或者IN/OUT assignment error。解决办法是看提示信息和出错行,用INT_TO_REALREAL_TO_INTDINT_TO_INT等转换函数处理。

第二类:变量未声明或拼写错误。ST是严格区分大小写的,bStartbstart是两个不同的变量。如果你声明了bStart,代码里写bstart,编译会报"变量未声明"。这类错误编译期就能拦住,关键是别图省事随手用缩写命名。

第三类:数组越界。运行时会出现程序异常或数据错乱。H5U的ST有严格的数组边界检查,一旦写入arrData[8]而数组定义是ARRAY[0..7],PLC会直接报运行时错误。排查时优先检查所有FOR循环的边界条件。

第四类:逻辑顺序问题。程序是按扫描周期从上到下执行的,不同于C语言的调用顺序。比如你第一行把bRun置为TRUE,第二行又判断IF bStop THEN bRun := FALSE,如果停止按钮已经松开了,那第二行不执行,bRun保持TRUE。这个顺序问题是最隐蔽的,排查方法就是把监视窗口的扫描周期打开,观察每个扫描周期变量的变化顺序。

5.4 一个综合案例:温度报警+平均滤波+电机联动的完整ST程序

最后给一个综合程序框架,把前面学到的所有语法串起来。这个程序完成的功能是:读取4路模拟量温度,做平均滤波后,当平均温度超过阈值且电机处于运行状态时,输出报警灯并停止电机。

VAR // 模拟量原始值 arrAD : ARRAY[0..3] OF INT; // 转换后的温度 arrTemp : ARRAY[0..3] OF REAL; // 平均温度 rAvgTemp : REAL := 0.0; // 电机控制 fbMainMotor : FB_Motor; bOverTemp : BOOL := FALSE; i : INT; END_VAR // 第一步:批量温度转换 FOR i := 0 TO 3 DO arrTemp[i] := INT_TO_REAL(arrAD[i]) * 0.1; END_FOR // 第二步:求平均温度 rAvgTemp := 0.0; FOR i := 0 TO 3 DO rAvgTemp := rAvgTemp + arrTemp[i]; END_FOR rAvgTemp := rAvgTemp / 4.0; // 第三步:超温判断 bOverTemp := rAvgTemp > 85.0; // 第四步:电机联动 fbMainMotor(bStart := %IX0.0, bStop := %IX0.1, bFault := bOverTemp); %QX0.0 := fbMainMotor.bRun; // 第五步:报警灯(超温且电机仍在运行,说明异常) %QX0.1 := bOverTemp AND fbMainMotor.bRun;

这个程序麻雀虽小五脏俱全:用了数组、类型转换、FOR循环、功能块实例化、条件判断、输出映射。你把这套结构跑通了,H5U的ST入门就算真正完成了。

我在实际调试这种综合程序时有一条心得:每加一段逻辑就先用在线监视确认这一段的行为,不要全部写完才一次性调试。故障定位的时候,分成"采集-计算-判断-联动"四层来排查,比从头到尾一行行看代码要快一个数量级。

这个系列后续还可以继续往深处走,比如ST和EtherCAT运动控制的结合、ST里如何做凸轮表和电子齿轮的运算、H5U和HMI的配方数据交互,这些都是ST比梯形图有明显优势的领域。如果你把基础7步吃透,这些内容学起来会顺畅很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 10:44:57

SpringBoot校园一卡通系统开发实战:从数据库设计到部署全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 10:42:31

能源互联网统一接入平台:CPS架构下的多协议适配与设备协同实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 10:38:38

A100 GPU适合哪些AI任务?从训练、微调到推理的算力配置分析

A100属于NVIDIA Ampere架构的数据中心GPU&#xff0c;面向AI、数据分析和高性能计算等工作负载。对于需要租赁GPU算力的企业来说&#xff0c;A100是否合适&#xff0c;主要取决于模型显存需求、计算负载以及多卡通信需求。A100 40GB和80GB的区别A100有40GB和80GB等显存规格。NV…

作者头像 李华
网站建设 2026/9/24 10:19:55

传输快的免费网盘推荐 大文件不限速传输产品选择参考

传输快的免费网盘选型核心要点选传输快的免费网盘需重点关注是否限速、带宽上限、单文件大小限制、断点续传、就近节点接入五大核心要点。对于有大文件传输需求的用户来说&#xff0c;传统网盘普遍存在的隐形限速、单文件大小限制、传输中断后需重传等问题&#xff0c;会大幅降…

作者头像 李华
网站建设 2026/9/24 10:19:52

TikTok店群玩法如何破解批量上新与重复铺货难题?一文全解析

TikTok店群模式依靠多店分散布局、多点抢占流量的优势&#xff0c;成为不少卖家扩大商品覆盖范围、测试市场机会的重要运营方式。然而&#xff0c;若想保持稳定的出单与增长节奏&#xff0c;离不开持续、批量的商品上新&#xff0c;并通过丰富的货品池获得更多流量曝光机会。但…

作者头像 李华