4

I try to calculate the CRC16 for m-bus messages in go.

One example is in the following document on page 4: http://fastforward.ag/downloads/docu/FAST_EnergyCam-Protocol-wirelessMBUS.pdf

10 data bytes and the checksum (HEX): 1244C418641610230102 B92F

The Polynom is x^16+x^13+x^12+x^11+x^10+x^8+x^6+x^5+x^2+1 or 0x3D65

Not sure what I'm doing wrong, but I tied a lot of online CRC calculators and none gives me the expected checksum. I try to calculate the CRC16 with github.com/howeyc/crc16 but even here I get a lot of different values depending on the parameters but never the correct ones.

I also have some live samples with the same issue: 2e44b05c12130000021b 8a66, 23446532710501883408 0607

I would take any hin or implementation that helps to find the correct crc.

Thanks.

Edit: Okay I got it. I ended up with 2 functions to calculate the CRC:

func updateBitsReversed(crc uint16, tab *Table, p []byte) uint16 {
    for _, v := range p {
        crc = tab[byte(crc>>8)^v] ^ (crc << 8)
    }
    return crc
}

func update(crc uint16, tab *Table, p []byte) uint16 {
    crc = ^crc
    for _, v := range p {
        crc = tab[byte(crc)^v] ^ (crc >> 8)
    }
    return ^crc
}

With the correct table and updateBitsReversed it now works.

Let me rephrase my question: When do I need to invert the initial crc before calculating the rest? It is just a convention defined by some CRCs?

Tarion
  • 16,283
  • 13
  • 71
  • 107

1 Answers1

0

Giving a bit of background: For CRC16 there are several parameters you need to take care of. There is the polynomial, and the initial value to use (either 0x0000 or 0xffff for most cases). Also, the bits of a byte can be reflected on input (meaning the order of the bits will we inverted, the byte will be mirrored). The output can also be reflected, but here you would invert the 16 bits of the calculated value. And there is a final step where the result is XORed with a constant value (proprietary implementations like to do that with arbitrary values, according to Wikipedia). Your inversion at the end is a special case of that using 0xffff for the final XOR.

For wMBus those parameters would be:

polynomial: 0x3d65
initial:    0x0000
finalXOR:   0xffff
reflectIn:  false
reflectOut: false

So long story short, your final inversion at the return of your update() function does the trick, your error would be in the crc = ^crc. It should work if you change your function to this:

func update(crc uint16, tab *Table, p []byte) uint16 {
    for _, v := range p {
        crc = tab[byte(crc)^v] ^ (crc >> 8)
    }
    return ^crc
}

If you need more information, an extensive explanation of CRC can be found at sunshine2k.de; the parameters are explained in chapter 7: CRC algorithm specification.

kratenko
  • 7,354
  • 4
  • 36
  • 61