CRC16 calculate

Hello,
with my application I have to work a "SMART HOPPER" INNOVATIVE the problem is that I can not calculate
the CRC16 to be inserted in the communication strings.
Attached the part of the datascheet that contains explanation and library crc16.
I intercepted communication, this is string working 7F 90 01 11 26 03 (CRC16 is calculated on 3 bytes, 90 01 11, result is 26 03) I can not calculate this, my result is B1 C1, I tried to put 3 bytes on the calculator online but I can never get a result
26 03.
This is test code
thanks

#include "crc16.h"

unsigned int myCrc16;

void setup() {
  Serial.begin(9600);
   byte uno = 0x90;
   byte due = 0x01;
   byte tre = 0x11;
   byte crc[3] = {uno,due,tre};
   myCrc16 = calc_crc16(crc, 3);
   Serial.print(F("CRC16 = 0x"));
   Serial.println(myCrc16, HEX);
}

void loop() {

}

crc.zip (3.63 KB)

There are many variations of CRC16. The bit stream can be input forward or backwards; there are XOR input and output options, different polynomials, etc.

:sob: yes I know but in the manual (see attached screenshot) is specified how to calculate, it seems to be classic way (X16 + X15 + X2 +1) initialized to 0xFFFF but I can not get that result

I contacted INNOVATIVE for information. they sent me what is the calculation method.
I'm not very experienced, is there any way to integrate this with arduino?
thank you

*/ 
#define FALSE           0x00 
#define TRUE            0x01 
unsigned char CRCL,CRCH; 
int CRC_Table[8*32]={ 
0x0000,0x8005,0x800F,0x000A,0x801B,0x001E,0x0014,0x8011, 
0x8033,0x0036,0x003C,0x8039,0x0028,0x802D,0x8027,0x0022, 
0x8063,0x0066,0x006C,0x8069,0x0078,0x807D,0x8077,0x0072, 
0x0050,0x8055,0x805F,0x005A,0x804B,0x004E,0x0044,0x8041, 
0x80C3,0x00C6,0x00CC,0x80C9,0x00D8,0x80DD,0x80D7,0x00D2, 
0x00F0,0x80F5,0x80FF,0x00FA,0x80EB,0x00EE,0x00E4,0x80E1, 
0x00A0,0x80A5,0x80AF,0x00AA,0x80BB,0x00BE,0x00B4,0x80B1, 
0x8093,0x0096,0x009C,0x8099,0x0088,0x808D,0x8087,0x0082, 
0x8183,0x0186,0x018C,0x8189,0x0198,0x819D,0x8197,0x0192, 
0x01B0,0x81B5,0x81BF,0x01BA,0x81AB,0x01AE,0x01A4,0x81A1, 
0x01E0,0x81E5,0x81EF,0x01EA,0x81FB,0x01FE,0x01F4,0x81F1, 
0x81D3,0x01D6,0x01DC,0x81D9,0x01C8,0x81CD,0x81C7,0x01C2, 
0x0140,0x8145,0x814F,0x014A,0x815B,0x015E,0x0154,0x8151, 
0x8173,0x0176,0x017C,0x8179,0x0168,0x816D,0x8167,0x0162, 
0x8123,0x0126,0x012C,0x8129,0x0138,0x813D,0x8137,0x0132, 
0x0110,0x8115,0x811F,0x011A,0x810B,0x010E,0x0104,0x8101, 
0x8303,0x0306,0x030C,0x8309,0x0318,0x831D,0x8317,0x0312, 
0x0330,0x8335,0x833F,0x033A,0x832B,0x032E,0x0324,0x8321, 
0x0360,0x8365,0x836F,0x036A,0x837B,0x037E,0x0374,0x8371, 
0x8353,0x0356,0x035C,0x8359,0x0348,0x834D,0x8347,0x0342, 
0x03C0,0x83C5,0x83CF,0x03CA,0x83DB,0x03DE,0x03D4,0x83D1,
0x83F3,0x03F6,0x03FC,0x83F9,0x03E8,0x83ED,0x83E7,0x03E2, 
0x83A3,0x03A6,0x03AC,0x83A9,0x03B8,0x83BD,0x83B7,0x03B2, 
0x0390,0x8395,0x839F,0x039A,0x838B,0x038E,0x0384,0x8381, 
0x0280,0x8285,0x828F,0x028A,0x829B,0x029E,0x0294,0x8291, 
0x82B3,0x02B6,0x02BC,0x82B9,0x02A8,0x82AD,0x82A7,0x02A2, 
0x82E3,0x02E6,0x02EC,0x82E9,0x02F8,0x82FD,0x82F7,0x02F2, 
0x02D0,0x82D5,0x82DF,0x02DA,0x82CB,0x02CE,0x02C4,0x82C1, 
0x8243,0x0246,0x024C,0x8249,0x0258,0x825D,0x8257,0x0252, 
0x0270,0x8275,0x827F,0x027A,0x826B,0x026E,0x0264,0x8261, 
0x0220,0x8225,0x822F,0x022A,0x823B,0x023E,0x0234,0x8231, 
0x8213,0x0216,0x021C,0x8219,0x0208,0x820D,0x8207,0x0202}; 

 

//------------------------------------------------------------------------ 
void Update_CRC(unsigned char num){ 
unsigned int  table_addr; 
  table_addr=(num ^ CRCH); 
  CRCH=(CRC_Table[table_addr] >> 8) ^ CRCL; 
  CRCL=(CRC_Table[table_addr] & 0x00FF); 
} 

 

//------------------------------------------------------------------------ 
void Reset_CRC(void){ 
  CRCL=0xFF; 
  CRCH=0xFF; 
}

Yes, absolutely. Just little problem with the table is that it takes 512B. It can be too much for the memory, e.g UNO has just 2k of RAM. The solution is to use the table directly from the FLASH memory, but it is bit slower access.

This works, and returns

CRC16 = 0x326

.
The order of the bytes is different than what appears in your first post. As Budvar10 suggests, put the table in program memory using the PROGMEM keyword and use the associated functions to read it out.

unsigned char CRCL, CRCH;

int CRC_Table[8 * 32] = {
  0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
  0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
  0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
  0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
  0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
  0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
  0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
  0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
  0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
  0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
  0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
  0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
  0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
  0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
  0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
  0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
  0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
  0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
  0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
  0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
  0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
  0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
  0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
  0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
  0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
  0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
  0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
  0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
  0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
  0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
  0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
  0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
};



//------------------------------------------------------------------------
void Update_CRC(unsigned char num) {
  unsigned int  table_addr;
  table_addr = (num ^ CRCH);
  CRCH = (CRC_Table[table_addr] >> 8) ^ CRCL;
  CRCL = (CRC_Table[table_addr] & 0x00FF);
}



//------------------------------------------------------------------------
void Reset_CRC(void) {
  CRCL = 0xFF;
  CRCH = 0xFF;
}
void setup() {
  Serial.begin(9600);
  unsigned char uno = 0x90;
  unsigned char due = 0x01;
  unsigned char tre = 0x11;
  unsigned char crc[3] = {uno, due, tre};

  Reset_CRC();
  for (int i = 0; i < 3; i++) {
    Update_CRC(crc[i]);
  }

  Serial.print(F("CRC16 = 0x"));
  Serial.print(CRCH, HEX);
  Serial.println(CRCL, HEX);
}

void loop() {

}

This code doesn't use a lookup table. It will be slower but smaller. As long as you aren't using very long messages this should be fast enough.

// This uses CRC16 ANSI (modified by Pete El_Supremo)
// Data from: https://forum.arduino.cc/index.php?topic=533304.0 

// This code originally generated the xmodem CRC posted
// by Pete El_Supremo in:
// http://forum.arduino.cc/index.php?topic=529288.0
char CRC1 [3] = {
  // CRC is 0x2603
  0x90, 0x01, 0x11
};

void setup(void)
{
  uint16_t crc_out;
  Serial.begin(9600);
  while(!Serial);

  crc_out = calc_crc(CRC1,3); //Calculate CRC on-the-fly
  Serial.println(crc_out,HEX);
}

void loop(void)
{
}


uint16_t calc_crc(char *msg,int n)
{
  // Initial value is 0xFFFF
  uint16_t x = 0xFFFF;

  while(n--) {
    x = crc_update(x, (uint16_t)*msg++);
  }
  return(x);
}

// Polynomial is 0x8005 (Koopman calls this ANSI-16 0xC002)
uint16_t crc_update (uint16_t crc, uint8_t data)
{
  int i;

  crc = crc ^ ((uint16_t)data << 8);
  for (i=0; i<8; i++) {
    if (crc & 0x8000)
      crc = (crc << 1) ^ 0x8005; //(polynomial = 0x8005)
    else
      crc <<= 1;
  }
  return crc;
}

It is a modified version of the code I posted to XMODEM CRC here

Pete