文章目录

西门子PLC的字符串分割函数实现

发布于 2026-03-23 22:10:46 · 浏览 4 次 · 评论 0 条

在工业自动化场景中,经常需要处理来自扫码枪、RFID 阅读器或上位机下发的字符串数据。这些数据通常包含多个信息段,例如“批次号 - 日期 - 流水号”,需要通过分隔符将其拆解为独立的变量以便后续逻辑处理。西门子 S7-1200/1500 PLC 虽内置了部分字符串指令,但并未直接提供类似高级语言的“Split”函数。本文将手把手教你使用 SCL 语言编写一个通用的字符串分割功能块。


准备工作

在开始编写代码前,请确认你的开发环境满足以下基本条件。这能避免后续出现指令不支持或编译报错的问题。

  1. 软件版本:确保安装的 TIA Portal 版本为 V15 或更高。低版本对字符串指令的支持较弱,可能缺少 FINDLEN 等关键函数。
  2. 硬件型号:本项目适用于 S7-1200 或 S7-1500 系列 PLC。S7-200 SMART 或老款 S7-300/400 需要采用不同的梯形图逻辑,不适用本教程。
  3. 编程语言:建议使用 SCL(结构化控制语言)。虽然梯形图也能实现,但处理字符串循环和数组索引时,SCL 的代码量和可读性优势巨大。

核心逻辑设计

字符串分割的本质是循环查找分隔符的位置,并截取两个分隔符之间的字符。为了让你直观理解程序运行流程,请参考下方的逻辑流程图。

graph TD A["开始:初始化索引 i=0"] --> B["查找分隔符位置 Pos"] B --> C{"是否找到?"} C -- "否 (剩余最后一部分)" --> D["提取剩余字符串"] C -- "是" --> E["提取分隔符前字符串"] E --> F["更新起始位置 StartPos"] F --> G["索引 i 加 1"] G --> B D --> H["保存结果到数组"] H --> I["结束"]

上图展示了程序如何通过循环不断切割字符串。关键在于记录当前的“起始位置”,每次找到分隔符后,更新起始位置为“当前分隔符位置 + 1",从而跳过已处理的部分。


步骤一:创建功能块

首先需要在项目中建立专用的功能块,以便重复调用。

  1. 打开 项目树,右键点击“程序块”文件夹。
  2. 选择 “添加新块”,在弹出的窗口中勾选 “函数块 (FB)"。
  3. 输入 名称为 FB_StringSplit,语言选择 SCL
  4. 点击 “确定”生成空白块。

步骤二:定义接口变量

接口定义决定了功能块的易用性。我们需要输入原始字符串、分隔符,输出分割后的字符串数组。请在 FB_StringSplit 的接口区域输入以下变量。

变量名称 数据类型 方向 说明
InputString String Input 待分割的原始字符串
Delimiter Char Input 分隔符字符,如 '-' 或 ','
MaxParts Int Input 最大分割段数,防止数组溢出
OutputArray Array[0..9] of String Output 存储分割结果的字符串数组
PartCount Int Output 实际分割出的段数
StartPosition Int Static 内部变量,记录当前查找起点
FoundPos Int Static 内部变量,记录找到分隔符的位置
Index Int Static 内部变量,循环计数器

注意:OutputArray 的大小应根据实际需求调整。上表定义为 10 段(0 到 9),若需要更多段数,请修改 数组上限。静态变量 Static 用于在扫描周期内保持中间计算状态,避免数据丢失。


步骤三:编写 SCL 代码

双击打开 FB_StringSplit 的编程界面,删除 默认生成的注释,复制 以下代码并粘贴 到编辑区。代码已添加详细注释,解释每一行的作用。

// 初始化变量
#Index := 0;
#StartPosition := 1; // SCL 字符串索引通常从 1 开始
#PartCount := 0;

// 获取输入字符串长度
#TempLength := LEN(#InputString);

// 开始循环处理
WHILE #StartPosition <= #TempLength AND #Index < #MaxParts DO
    // 查找分隔符位置,从当前起始位置开始找
    #FoundPos := FIND(#InputString, #Delimiter, #StartPosition);

    IF #FoundPos > 0 THEN
        // 找到分隔符,截取左侧部分
        // MID 函数参数:原字符串,起始位置,长度
        #OutputArray[#Index] := MID(#InputString, #StartPosition, #FoundPos - #StartPosition);

        // 更新起始位置到分隔符之后
        #StartPosition := #FoundPos + 1;

        // 计数器加 1
        #Index := #Index + 1;
    ELSE
        // 未找到分隔符,说明是最后一部分
        // 截取剩余所有字符
        #OutputArray[#Index] := MID(#InputString, #StartPosition, #TempLength - #StartPosition + 1);

        // 计数器加 1
        #Index := #Index + 1;

        // 退出循环
        EXIT;
    END_IF;
END_WHILE;

// 输出实际分割的段数
#PartCount := #Index;

注意:部分旧版本固件可能不支持 MID 函数,若编译报错,请使用 LEFTRIGHT 组合替代,或升级固件。上述代码假设 LENFIND 指令可用,这是 S7-1200/1500 的标准库函数。


步骤四:调用与测试

功能块编写完成后,需要在主程序中进行调用并验证效果。

  1. 打开 主程序块(如 Main [OB1])。
  2. 拖拽 FB_StringSplit 到程序编辑区。
  3. 创建 一个背景数据块,命名为 DB_Split_Instance
  4. 输入 测试数据。在全局数据块或监控表中定义 以下变量用于测试:
    • TestInput (String): 输入 "A01-B02-C03"
    • TestDelim (Char): 输入 '-'
    • ResultArray (Array of String): 用于接收结果
  5. 关联 引脚。将 TestInput 连接到 InputStringTestDelim 连接到 DelimiterResultArray 连接到 OutputArray
  6. 下载 程序到 PLC 并运行
  7. 监控 DB_Split_Instance 数据块。观察 OutputArray 是否依次显示 "A01", "B02", "C03",且 PartCount 显示为 3

常见问题排查

如果在测试过程中发现结果不正确,请按照以下清单逐项检查。

现象 可能原因 解决方法
结果全为空 起始位置索引错误 确认 PLC 字符串索引是从 0 还是 1 开始,SCL 通常为 1
数组溢出报错 分割段数超过设定 增大 MaxParts 参数或检查输入字符串分隔符数量
最后一次截取缺失 循环条件过早结束 检查 ELSE 分支是否正确处理了末尾无分隔符的情况
包含分隔符字符 截取长度计算错误 确认 MID 函数的长度参数是否减去了分隔符占用位

特别注意字符串长度计算。某些情况下,字符串实际长度可能包含末尾的空字符填充。使用 LEN 函数获取的是有效字符长度,而非数组定义长度。若发现截取结果包含乱码,请确保在截取前使用 LEN 函数动态计算长度,而非直接使用数组定义大小。

对于连续分隔符的情况(如 "A--B"),上述逻辑会将中间部分识别为空字符串。若业务不允许空字符串,需在截取后增加 判断逻辑:若 #OutputArray[#Index] 长度为 0,则跳过 该次计数,不增加 #Index,继续下一次循环查找。

若需要处理多个不同分隔符(如同时支持逗号和分号),可修改 FIND 逻辑,先查找第一个分隔符位置,再查找第二个,取最小值作为切割点。这需要嵌套 IF 判断或编写辅助函数比较位置大小。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文