如何计算纵向冗余校验(LRC)?

时间:2012-10-09 11:32:18

标签: c# checksum parity

我已经尝试过维基百科的例子:http://en.wikipedia.org/wiki/Longitudinal_redundancy_check

这是lrc(C#)的代码:

/// <summary>
/// Longitudinal Redundancy Check (LRC) calculator for a byte array. 
/// ex) DATA (hex 6 bytes): 02 30 30 31 23 03
///     LRC  (hex 1 byte ): EC    
/// </summary> 
public static byte calculateLRC(byte[] bytes)
{
    byte LRC = 0x00;
    for (int i = 0; i < bytes.Length; i++)
    {
        LRC = (LRC + bytes[i]) & 0xFF; 
    }
    return ((LRC ^ 0xFF) + 1) & 0xFF;
}   

它说结果是&#34; EC&#34;但我得到&#34; 71&#34;,我做错了什么?

感谢。

6 个答案:

答案 0 :(得分:8)

这是一个清理过的版本,它没有完成所有那些无用的操作(而不是每次都丢弃高位,最后一次丢弃它们),它给出了你观察到的结果。这是使用加法的版本,但最后有一个否定 - 也可以减去并跳过否定。即使在溢出的情况下,这也是一种有效的转换。

public static byte calculateLRC(byte[] bytes)
{
    int LRC = 0;
    for (int i = 0; i < bytes.Length; i++)
    {
        LRC -= bytes[i];
    }
    return (byte)LRC;
}

这是替代LRC(简单的字节xor)

public static byte calculateLRC(byte[] bytes)
{
    byte LRC = 0;
    for (int i = 0; i < bytes.Length; i++)
    {
        LRC ^= bytes[i];
    }
    return LRC;
}

在这种情况下,维基百科在代码(不编译)和预期结果中都是错误的。

答案 1 :(得分:4)

猜猜这个看起来更酷;)

public static byte calculateLRC(byte[] bytes)
{
    return bytes.Aggregate<byte, byte>(0, (x, y) => (byte) (x^ y));
}

答案 2 :(得分:3)

如果有人想从字符串中获取LRC字符:

    public static char CalculateLRC(string toEncode)
    {
        byte[] bytes = Encoding.ASCII.GetBytes(toEncode);
        byte LRC = 0;
        for (int i = 0; i < bytes.Length; i++)
        {
            LRC ^= bytes[i];
        }
        return Convert.ToChar(LRC);
    }

答案 3 :(得分:0)

更正的维基百科版本如下:

private byte calculateLRC(byte[] b)
    {
        byte lrc = 0x00;
        for (int i = 0; i < b.Length; i++)
        {
            lrc = (byte)((lrc + b[i]) & 0xFF);
        }
        lrc = (byte)(((lrc ^ 0xff) + 2) & 0xFF);
        return lrc;
    }

答案 4 :(得分:0)

我为Arduino创建了此文件以了解算法(当然,它并不是以最有效的方式编写的)

String calculateModbusAsciiLRC(String input)
{
  //Refer this document http://www.simplymodbus.ca/ASCII.htm

  if((input.length()%2)!=0) { return "ERROR COMMAND SHOULD HAVE EVEN NUMBER OF CHARACTERS"; } 
 // Make sure to omit the semicolon in input string and input String has even number of characters

   byte byteArray[input.length()+1];
   input.getBytes(byteArray, sizeof(byteArray));
    byte LRC = 0;
    for (int i = 0; i <sizeof(byteArray)/2; i++)
    {
      // Gettting the sum of all registers
     uint x=0;
     if(47<byteArray[i*2] && byteArray[i*2] <58) {x=byteArray[i*2] -48;}
     else { x=byteArray[i*2] -55;     }
       uint y=0;
     if(47<byteArray[i*2+1] && byteArray[i*2+1] <58) {y=byteArray[i*2+1] -48;}
     else { y=byteArray[i*2+1] -55;     }
     LRC  += x*16 + y;
    }   
    LRC = ~LRC + 1;   // Getting twos Complement
    String checkSum = String(LRC, HEX);
    checkSum.toUpperCase(); // Converting to upper case eg: bc to BC - Optional somedevices are case insensitve 
    return checkSum;
} 

答案 5 :(得分:-1)

我意识到这个问题很老了,但我很难搞清楚如何做到这一点。它现在正在工作,所以我想我应该粘贴代码。在我的例子中,校验和需要作为ASCII字符串返回。

public function getLrc($string)
{
    $LRC = 0;
    // Get hex checksum.
    foreach (str_split($string, 1) as $char) {
        $LRC ^= ord($char);
    }
    $hex = dechex($LRC);
    // convert hex to string
    $str = '';
    for($i=0;$i<strlen($hex);$i+=2) $str .= chr(hexdec(substr($hex,$i,2)));
    return $str;
}