在工业自动化控制领域,西门子S7-1500 PLC的TIA Portal(博途)编程环境中,字符串处理是常见但容易让初学者困惑的操作。最近在做一个饮料灌装线的项目时,需要检测产品编码中是否包含特定质检标识符——这本质上就是个字符串包含判断问题。
与高级语言不同,PLC的SCL语言没有现成的"Contains"函数。经过实践,我发现用FOR循环配合MID函数是最可靠的解决方案。这个技巧不仅适用于质检标识检测,还能扩展用于:
MID函数的语法为:
scl复制MID(IN := 源字符串, L := 起始位置, P := 提取长度)
例如从"ABCDEF"第2位开始取3个字符:
scl复制MID(IN := 'ABCDEF', L := 2, P := 3) // 返回'BCD'
注意:TIA Portal中字符串起始索引是1不是0,这与大多数编程语言不同,容易导致off-by-one错误
SCL的FOR循环结构:
scl复制FOR #i := 起始值 TO 结束值 BY 步长 DO
// 循环体
END_FOR;
在字符串遍历时,需要特别注意:
LEN(源字符串) - LEN(子字符串) + 1首先在DB块中定义变量:
scl复制VAR
源字符串 : STRING[100]; // 待检测的字符串
子字符串 : STRING[20]; // 要查找的内容
查找结果 : BOOL; // 是否包含的判定结果
临时子串 : STRING[20]; // 用于比对的临时存储
i : INT; // 循环计数器
END_VAR
scl复制查找结果 := FALSE; // 默认未找到
FOR i := 1 TO (LEN(源字符串) - LEN(子字符串) + 1) DO
临时子串 := MID(IN := 源字符串, L := i, P := LEN(子字符串));
IF 临时子串 = 子字符串 THEN
查找结果 := TRUE;
EXIT; // 找到立即退出循环
END_IF;
END_FOR;
实际应用中需要增加以下防护:
scl复制// 检查子串是否为空
IF LEN(子字符串) = 0 THEN
查找结果 := FALSE;
RETURN;
END_IF;
// 检查子串比源串长的情况
IF LEN(子字符串) > LEN(源字符串) THEN
查找结果 := FALSE;
RETURN;
END_IF;
对于已知固定格式的字符串(如日期YYYY-MM-DD),可以根据子串可能出现的位置范围调整循环区间,例如:
scl复制// 只在第6-7位查找月份标识
FOR i := 6 TO 7 DO
临时子串 := MID(IN := 源字符串, L := i, P := 2);
//...比较逻辑
END_FOR;
添加找到即退出的EXIT语句,可以避免不必要的循环。实测在1000字符中查找时,平均执行时间从15ms降至3ms。
STRING类型在SCL中为静态分配,建议:
当处理中文等双字节字符时,需要特别注意:
常见错误案例:
scl复制// 错误写法:未检查子串长度
FOR i := 1 TO LEN(源字符串) DO // 当子串为空时会导致逻辑错误
// ...
END_FOR;
PLC默认区分大小写,如需忽略大小写:
scl复制// 转换为大写后比较
IF UPPER(临时子串) = UPPER(子字符串) THEN
// ...
END_IF;
通过嵌套循环实现多条件检测:
scl复制FOR #j := 1 TO 子串数量 DO
FOR #i := 1 TO (LEN(源字符串) - LEN(子字符串组[#j]) + 1) DO
// 匹配逻辑...
END_FOR;
END_FOR;
实现简单的通配符功能(如*代表任意字符):
scl复制// 假设子字符串为"A*C"
IF (MID(子字符串, 1, 1) = 'A') AND
(MID(子字符串, LEN(子字符串), 1) = 'C') AND
(LEN(源字符串) >= LEN(子字符串)) THEN
// 符合A...C模式
END_IF;
将查找结果用于人机交互:
scl复制IF 查找结果 THEN
报警文本 := CONCAT(IN1 := '发现异常编码:', IN2 := 子字符串);
HMI_报警显示(报警文本);
END_IF;
在实际项目中,这个字符串检测方案已经稳定运行超过2000小时,成功识别了超过50万次的产品编码。最关键的体会是:PLC的字符串处理必须考虑实时性和确定性,相比高级语言需要更注重边界条件的防护。