zoukankan      html  css  js  c++  java
  • // 生成modbus CRC16数据

         CRC-16 / MODBUS :
    
    1)CRC寄存器初始值为 FFFF;即16个字节全为1;
    
    2)CRC-16 / MODBUS的多项式A001H (1010 0000 0000 0001B) ‘H’表示16进制数,‘B’表示二进制数
    
    计算步骤为: 
    (1).预置 16 位寄存器为十六进制 FFFF(即全为 1) ,称此寄存器为 CRC  寄存器;  
    (2).把第一个 8  位数据与 16  位 CRC  寄存器的低位相异或,把结果放于 CRC  寄
    存器; 
    
    (3).检测相异或后的CRC寄存器的最低位,若最低位为1:CRC寄存器先右移1位,再与多项式A001H进行异或;若为0,则CRC寄存器右移1位,无需与多项式进行异或。
    
    (4).重复步骤 3  ,直到右移 8  次,这样整个 8 位数据全部进行了处理; 
    (5).重复步骤 2  到步骤4,进行下一个 8  位数据的处理; 
    (6).最后得到的 CRC  寄存器即为 CRC 码。 
    
    附参考:
    
    数据(16进制):01 03 61 00 00 02 CRC校验:F7 DB
    
    附C语言实现代码:
    
    
    #include <stdio.h>
    
    int main(void)
    {
        unsigned short tmp = 0xffff;
        unsigned short ret1 = 0;
        unsigned char buff[6] = {0};
        buff[0] = 0x01;
        buff[1] = 0x03;
        buff[2] = 0x61;
        buff[3] = 0x00;
        buff[4] = 0x00;
        buff[5] = 0x02;
    
        for(int n = 0; n < 6; n++){/*此处的6 -- 要校验的位数为6个*/
            tmp = buff[n] ^ tmp;
            for(int i = 0;i < 8;i++){  /*此处的8 -- 指每一个char类型又8bit,每bit都要处理*/
                if(tmp & 0x01){
                    tmp = tmp >> 1;
                    tmp = tmp ^ 0xa001;
                }
                else{
                    tmp = tmp >> 1;
                }
            }
        }
        /*CRC校验后的值*/
        printf("%X
    ",tmp);
        /*将CRC校验的高低位对换位置*/
        ret1 = tmp >> 8;
        ret1 = ret1 | (tmp << 8);
        printf("ret: %X
    ",ret1);
        return 0;
    }
    输出结果:
    
    F7DB
    ret: DBF7
    
    
    
    // 生成modbus CRC16数据
    function CRC16(sSrc:shortstring):shortstring;
    var
      tmp: word;
      ret1: word;
      buff: array of byte;
      n:integer;
      i:integer;
    
      ilen:Integer; //ssrc length
    begin
      if trim(ssrc)='' then exit;
    
      tmp:= $FFFF;
      ret1:= 0;
    
      ssrc:= Trim(ssrc);
      ssrc:= StringReplace(sSrc,' ','',[rfReplaceAll]);
      ilen:= length(ssrc);
    
      SetLength(buff,ilen div 2);
      i:=1;
      while i<ilen do
      begin
        buff[(i-1)div 2]:= StrToInt('$'+sSrc[i]+sSrc[i+1]);
        i:=i+2;
      end;
    
      for n := 0 to Length(buff)-1 do  //*此处的6 -- 要校验的位数为6个*/
      begin
        tmp:= buff[n] xor tmp;
        for I := 0 to 7 do  //*此处的8 -- 指每一个char类型又8bit,每bit都要处理*/
        begin
          if(tmp and $01)<>0 then
          begin
            tmp:= tmp shr 1;
            tmp:= tmp xor $A001;
          end
          else
          begin
            tmp:= tmp shr 1;
          end;
        end;
      end;
    
      ret1 := tmp shr 8;        //*将CRC校验的高低位对换位置*/
      ret1 := ret1 or (tmp shl 8);
      Result:= IntToHex(ret1,4);
    
      //返回16进制串 用 空格 分开  crc 暂定 2字节
      result:= Result[1]+Result[2]+' '+Result[3]+Result[4];
    end;
    书搞进脑袋 创新 创造; 积极
  • 相关阅读:
    docker映射端口无法访问
    Tomcat日志分析
    linux服务器性能测试
    mysql库表结构对比工具
    网络基础知识,不懂看这里
    Python之redis、mysql进程守护
    linux文件查找工具
    nginx解决跨域问题
    redis插入单个较大的键值
    linux系统安全巡检脚本
  • 原文地址:https://www.cnblogs.com/tobetterlife/p/12161832.html
Copyright © 2011-2022 走看看