0

I am trying to communicate an industrial type counter using Modbus. I have to calculate CRC16 value as two byte for send it. I previously googled for few Arduino libraries and I get a same function as below. But, I couldn't understand the function well.

I need CRC as two bytes and as input I have 6 bytes.

Can someone explain the below function and what are the argument I need to provide.

uint16_t crc16_update(uint16_t crc, uint8_t a)
  {
    int i;
    crc ^= a;
    for (i = 0; i < 8; ++i)
  {
    if (crc & 1)crc = (crc >> 1) ^ 0xA001;
    else crc = (crc >> 1);
  }
    return crc;
 }
3
  • 1
    I think you need to call the function for every byte of the date. First argument would be the CRC that was returned from the previous call. Second argument if the byte of data. Before you call it you need to set the CRC to 0xFFFF (first argument). – Gerben Mar 6 '19 at 13:38
  • 1
    Ugh. Calling a function for every byte seems inefficient. I'd suggest rewriting this to operate on a byte buffer. – Duncan C Mar 6 '19 at 13:41
  • The compiler will inline it for you. Just provide the optimizer flag. – Kwasmich Mar 7 '19 at 8:13
1

CRC-16 is just a term that describes an algorithm. There are multiple implementations possible. They not only differ by the used polynomial but also by the initial value.

Your particular implementation uses the IBM CRC-16 polynomial.

Other Possible polynomials are for example:
x^16 + x^15 + x^2 + 1 (IBM)
x^16 + x^12 + x^5 + 1 (CCITT)
x^16 + x^10 + x^8 + x^7 + x^3 + 1 (DECT)
(there are more on wikipedia)

Actually you can take any primitive polynomial. (UPDATE: Not using a primitive polynomial will reduce the output space but is still going to work.) So you will have to find out which one you have to use and then know the initial value.

Assume you are right with the IBM polynomial then assume the initial value is 0xffff. You use the function as follows:

uint16_t crc = 0xffff; // the initial value
uint8_t a[]; // your data
crc = crc16_update(crc, a[0]);
crc = crc16_update(crc, a[1]);
…
crc = crc16_update(crc, a[n]);
// done
// crc now holds the value of the data stored in a
3
  • Thanks @Kwasmich. My modbus counter need a byte array that has 6 data bytes and 2 CRC byte. Array length is 8 in total. I tried to get 2 CRC bytes using below data array. 0x01, 0x04, 0x03, 0xF4, 0x00, 0x01 it should be 0x70, 0x7C but I got 0x2E and 0x2B – user119o Mar 7 '19 at 5:48
  • That means that either your initial value and/or polynomial does not match your needs. – Kwasmich Mar 7 '19 at 7:28
  • This function working properly. Its the same to previous one and I have modified it for my requirement (a array with 6 element). gist.github.com/Nsk1107/c0875a55a5d30e00313d6de0930976bf Source: forum.arduino.cc/index.php?topic=421615.0 I cant realize why its working :/ :D – user119o Mar 7 '19 at 7:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.