【SCL编程案例】Modbus RTU 协议中的 CRC16 校验算法

已锁定

西门龍霆

  • 帖子

    35
  • 精华

    0
  • 被关注

    3

论坛等级:侠客

注册时间:2016-11-28

白金 白金 如何晋级?

【SCL编程案例】Modbus RTU 协议中的 CRC16 校验算法

3005

3

2025-09-05 09:49:06

这段代码实现了 Modbus RTU 协议中常用的 CRC16 校验算法,适用于西门子 S7 系列 PLC 的结构化文本(Structured Text, ST)环境。其主要功能是根据输入的字节数组(byInputArray)和指定的字节数(uiInNumBytes),计算出对应的 CRC16 校验值,并将高、低字节分别输出。

代码首先通过 LOWER_BOUND 和 UPPER_BOUND 获取输入数组的上下界,确保后续遍历不会越界。如果实际需要校验的字节数小于数组长度,则动态调整上界,仅对前 uiInNumBytes 个字节进行校验。CRC 的初始值设为 0xFFFF(标准 Modbus 起始值),多项式为 0xA001。

主循环依次处理每个字节,将其与当前 CRC 值异或。随后,内部嵌套的位循环对每一位进行右移操作,并根据最低位是否为 1 决定是否与多项式异或,实现 CRC16 的逐位计算。所有字节处理完毕后,最终的 CRC16 值被拆分为高、低字节输出


FUNCTION "fcCRC16_ModbusRTU" : Void

{ S7_Optimized_Access := 'TRUE' }

VERSION : 0.1

   VAR_INPUT

      uiInNumBytes : UInt; // 输入字节数

   END_VAR


   VAR_OUTPUT

      byOutCRCHigh : Byte; // 输出CRC高字节

      byOutCRCLow : Byte;  // 输出CRC低字节

   END_VAR


   VAR_IN_OUT

      byInputArray : Array[*] of Byte; // 输入字节数组

   END_VAR


   VAR_TEMP

      iTempLowerLimit : DInt; // 数组下界

      iTempUpperLimit : DInt; // 数组上界

      wTempCRC : Word;        // 临时CRC值

      iByteIndex : Int;       // 字节索引

      iBitIndex : Int;        // 位索引

      wTemp : Word;           // 临时变量

   END_VAR


   VAR CONSTANT

      cwXor : Word := 16#A001;   // CRC多项式

      cwStart : Word := 16#FFFF; // CRC初始值

   END_VAR



BEGIN

   #iTempLowerLimit := LOWER_BOUND(ARR := #byInputArray, DIM := 1); // 获取数组下界

   #iTempUpperLimit := UPPER_BOUND(ARR := #byInputArray, DIM := 1); // 获取数组上界

   

   IF #uiInNumBytes > 0 AND #uiInNumBytes <= (#iTempUpperLimit - #iTempLowerLimit + 1) THEN

       #iTempUpperLimit := #uiInNumBytes + #iTempLowerLimit - 1; // 根据输入字节数调整上界

   END_IF;

   

   #wTempCRC := #cwStart; // 初始化CRC

   

   FOR #iByteIndex := #iTempLowerLimit TO #iTempUpperLimit DO

       #wTempCRC := #wTempCRC XOR #byInputArray[#iByteIndex]; // 按字节异或

       FOR #iBitIndex := 0 TO 7 DO

           #wTemp := SHR(IN := #wTempCRC, N := 1); // 右移一位

           IF #wTempCRC.%X0 THEN

               #wTempCRC := #wTemp XOR #cwXor; // 若最低位为1,异或多项式

           ELSE

               #wTempCRC := #wTemp; // 否则直接赋值

           END_IF;

       END_FOR;

   END_FOR;

   

   #byOutCRCHigh := #wTempCRC.%B0; // 取高字节

   #byOutCRCLow := #wTempCRC.%B1;  // 取低字节

END_FUNCTION




【SCL编程案例】Modbus RTU 协议中的 CRC16 校验算法 已锁定
编辑推荐: 关闭

请填写推广理由:

本版热门话题

SIMATIC S7-1500系列

共有11188条技术帖

相关推荐

热门标签

相关帖子推荐

guzhang

恭喜,你发布的帖子

评为精华帖!

快扫描右侧二维码晒一晒吧!

再发帖或跟帖交流2条,就能晋升VIP啦!开启更多专属权限!

  • 分享

  • 只看
    楼主

top
X 图片
您收到0封站内信:
×
×
信息提示
很抱歉!您所访问的页面不存在,或网址发生了变化,请稍后再试。