UART communication with CRC

Hello,

After much research on the CRC implementation, I unfortunately failed to implement it. I found a lot of thread on this but can’t code it.
I am new to programming and Arduino. I would be grateful if anyone helps me.
Actually, I want to set up secure UART communication between my PC and Arduino Mega25. I want to send data with CRC code from the serial port of my PC to the Arduino. So for safety after many serach, I decided to use CRC_16_CCITT method.

Here is a simple code for example for the serial implementation. I want to add the CRC calculation to it.

#include <stdio.h>

void setup(){
Serial.begin(9600);
}

void loop(){
if (Serial.available() > 0){
char data = Serial.read();
Serial.println(data);
Serial.println(data, BIN);
}

I found an example (from carnetdumaker.net) like the following code in C, but not sure how can I make a code similar to my arduino code.

[color=#333333][color=#bc7a00]#include[/color] [color=#408080][i]<stdint.h>[/i][/color]


[color=#b00040]uint16_t[/color] [color=#0000ff]crc16_ccitt[/color]([color=#b00040]char[/color][color=#666666]*[/color] data, [color=#b00040]unsigned[/color] [color=#b00040]int[/color] data_len) {
 [color=#b00040]uint16_t[/color] crc [color=#666666]=[/color] [color=#666666]0xFFFF[/color];

 [color=#008000][b]if[/b][/color] (data_len [color=#666666]==[/color] [color=#666666]0[/color])
 [color=#008000][b]return[/b][/color] [color=#666666]0[/color];

 [color=#008000][b]for[/b][/color] ([color=#b00040]unsigned[/color] [color=#b00040]int[/color] i [color=#666666]=[/color] [color=#666666]0[/color]; i [color=#666666]<[/color] data_len; [color=#666666]++[/color]i) {
 [color=#b00040]uint16_t[/color] dbyte [color=#666666]=[/color] data[i];
 crc [color=#666666]^=[/color] dbyte [color=#666666]<<[/color] [color=#666666]8[/color];
 
 [color=#008000][b]for[/b][/color] ([color=#b00040]unsigned[/color] [color=#b00040]char[/color] j [color=#666666]=[/color] [color=#666666]0[/color]; j [color=#666666]<[/color] [color=#666666]8[/color]; [color=#666666]++[/color]j) {
 [color=#b00040]uint16_t[/color] mix [color=#666666]=[/color] crc [color=#666666]&[/color] [color=#666666]0x8000[/color];
 crc [color=#666666]=[/color] (crc [color=#666666]<<[/color] [color=#666666]1[/color]);
 [color=#008000][b]if[/b][/color] (mix)
 crc [color=#666666]=[/color] crc [color=#666666]^[/color] [color=#666666]0x1021[/color];
 }
 }

 [color=#008000][b]return[/b][/color] crc;
}[/color]

A CRC is used to determine the validity of data, not security. If you want a "secure UART communication" then you would need to apply some form of encryption/decryption to the data passed between the devices.

miilado:
I found an example (from carnetdumaker.net) like the following code in C, but not sure how can I make a code similar to my arduino code.

something like this you mean?
(compiles, not tested!)

/*CRC-16 CCITT
    CRC 16 bits
    Polynomial 0x1021
    Initial value 0xFFFF
    No inverted input
    No inverted output
    No final XOR (0x0000)
*/
uint16_t crc16_ccitt(int16_t* data, int16_t data_len) {
  uint16_t crc = 0xFFFF; //initial value

  if (data_len == 0)
    return 0;

  for (unsigned int i = 0; i < data_len; ++i) {
    uint16_t dbyte = data[i];
    crc ^= dbyte << 8;

    for (unsigned char j = 0; j < 8; ++j) {
      uint16_t mix = crc & 0x8000;
      crc = (crc << 1);
      if (mix)
        crc = crc ^ 0x1021; //polynomial
    }
  }

  return crc;
}

void setup() {
  uint16_t test_data[4] = {1, 2, 3, 4};

  Serial.begin(9600);

  Serial.println("***crc16_ccitt algorithm test***");
  Serial.print("Data set: ");
  for (int i = 0; i < 4; ++i) {
    Serial.print(test_data[i], DEC);
    Serial.print(", ");
  }
  Serial.print("\ncrc16_ccitt: ");
  Serial.print(crc16_ccitt(test_data, 4), DEC);
  Serial.println("");
}


void loop() {
  if (Serial.available() > 0) {
    char data = Serial.read();
    Serial.println(data);
    Serial.println(data, BIN);
  }
}

hope that helps…

markd833:
A CRC is used to determine the validity of data, not security. If you want a “secure UART communication” then you would need to apply some form of encryption/decryption to the data passed between the devices.

Thank you for your explination .
Hmm … so I think the validity would be sufficient in my case! How can I do it?

sherzaad:
something like this you mean?

uint16_t crc16_ccitt(int16_t* data, int16_t data_len) {

uint16_t crc = 0xFFFF;

if (data_len == 0)
   return 0;

for (unsigned int i = 0; i < data_len; ++i) {
   uint16_t dbyte = data;
   crc ^= dbyte << 8;

for (unsigned char j = 0; j < 8; ++j) {
     uint16_t mix = crc & 0x8000;
     crc = (crc << 1);
     if (mix)
       crc = crc ^ 0x1021;
   }
 }

return crc;
}

void setup() {
 uint16_t test_data[4] = {1, 2, 3, 4};

Serial.begin(9600);

Serial.println(“crc16_ccitt algorithm test”);
 Serial.print(“Data set: “);
 for (int i = 0; i < 4; ++i) {
   Serial.print(test_data[i], DEC);
   Serial.print(”, “);
 }
 Serial.print(”\ncrc16_ccitt: “);
 Serial.print(crc16_ccitt(test_data, 4), DEC);
 Serial.println(””);
}

void loop() {
 if (Serial.available() > 0) {
   char data = Serial.read();
   Serial.println(data);
   Serial.println(data, BIN);
 }
}




hope that helps...

Thank you for your reply.
I have some dobt here:
1- did you use the data that you get from Serial.read() in “crc16_ccitt” function? Because in “void loop()” the datatype of “data” is “char” but the datatype of “data” in “crc16_ccitt” is “int16_t* data” !
2- you calculated the crc but did not use it to transfer with data!
I want to add the “crc” code to the “data” that I get from Serial.read(), then print it out . → (data+crc)
Hope I am clear!
Thank you in advance,
Milad

I’ve implemented UART communication with CRC in SerialTransfer.h. Super easy to use and robust comms library. I chose to use an 8-bit CRC, but you should easily be able to scale the code to 16-bit if you really want to. Here’s the CRC code from my lib:

class PacketCRC
{
  public: // <<---------------------------------------//public
	uint8_t poly = 0;


	PacketCRC(const uint8_t& polynomial = 0x9B, const uint8_t& crcLen = 8)
	{
		poly      = polynomial;
		crcLen_   = crcLen;
		tableLen_ = pow(2, crcLen);
		csTable   = new uint8_t[tableLen_];

		generateTable();
	}

	void generateTable()
	{
		for (int i = 0; i < tableLen_; ++i)
		{
			int curr = i;

			for (int j = 0; j < 8; ++j)
			{
				if ((curr & 0x80) != 0)
					curr = (curr << 1) ^ (int)poly;
				else
					curr <<= 1;
			}

			csTable[i] = (byte)curr;
		}
	}

	void printTable()
	{
		for (int i = 0; i < tableLen_; i++)
		{
			Serial.print(csTable[i], HEX);

			if ((i + 1) % 16)
				Serial.print(' ');
			else
				Serial.println();
		}
	}

	uint8_t calculate(const uint8_t& val)
	{
		if (val < tableLen_)
			return csTable[val];
		return 0;
	}

	uint8_t calculate(uint8_t arr[], uint8_t len)
	{
		uint8_t crc = 0;
		for (uint16_t i = 0; i < len; i++)
			crc = csTable[crc ^ arr[i]];

		return crc;
	}


  private: // <<---------------------------------------//private
	uint16_t tableLen_;
	uint8_t  crcLen_;
	uint8_t* csTable;
};

Power_Broker:
I’ve implemented UART communication with CRC in SerialTransfer.h. Super easy to use and robust comms library. I chose to use an 8-bit CRC, but you should easily be able to scale the code to 16-bit if you really want to. Here’s the CRC code from my lib:

class PacketCRC

{
 public: // <<---------------------------------------//public
uint8_t poly = 0;

PacketCRC(const uint8_t& polynomial = 0x9B, const uint8_t& crcLen = 8)
{
	poly      = polynomial;
	crcLen_   = crcLen;
	tableLen_ = pow(2, crcLen);
	csTable   = new uint8_t[tableLen_];

	generateTable();
}

void generateTable()
{
	for (int i = 0; i < tableLen_; ++i)
	{
		int curr = i;

		for (int j = 0; j < 8; ++j)
		{
			if ((curr & 0x80) != 0)
				curr = (curr << 1) ^ (int)poly;
			else
				curr <<= 1;
		}

		csTable[i] = (byte)curr;
	}
}

void printTable()
{
	for (int i = 0; i < tableLen_; i++)
	{
		Serial.print(csTable[i], HEX);

		if ((i + 1) % 16)
			Serial.print(' ');
		else
			Serial.println();
	}
}

uint8_t calculate(const uint8_t& val)
{
	if (val < tableLen_)
		return csTable[val];
	return 0;
}

uint8_t calculate(uint8_t arr[], uint8_t len)
{
	uint8_t crc = 0;
	for (uint16_t i = 0; i < len; i++)
		crc = csTable[crc ^ arr[i]];

	return crc;
}

private: // <<---------------------------------------//private
uint16_t tableLen_;
uint8_t  crcLen_;
uint8_t* csTable;
};

Thank you for your help.
But I could not understand your method :frowning: :frowning: :frowning:

sherzaad:
something like this you mean?

uint16_t crc16_ccitt(int16_t* data, int16_t data_len) {

uint16_t crc = 0xFFFF;

if (data_len == 0)
   return 0;

for (unsigned int i = 0; i < data_len; ++i) {
   uint16_t dbyte = data;
   crc ^= dbyte << 8;

for (unsigned char j = 0; j < 8; ++j) {
     uint16_t mix = crc & 0x8000;
     crc = (crc << 1);
     if (mix)
       crc = crc ^ 0x1021;
   }
 }

return crc;
}

void setup() {
 uint16_t test_data[4] = {1, 2, 3, 4};

Serial.begin(9600);

Serial.println(“crc16_ccitt algorithm test”);
 Serial.print(“Data set: “);
 for (int i = 0; i < 4; ++i) {
   Serial.print(test_data[i], DEC);
   Serial.print(”, “);
 }
 Serial.print(”\ncrc16_ccitt: “);
 Serial.print(crc16_ccitt(test_data, 4), DEC);
 Serial.println(””);
}

void loop() {
 if (Serial.available() > 0) {
   char data = Serial.read();
   Serial.println(data);
   Serial.println(data, BIN);
 }
}




hope that helps...

Sorry, I understand better now!
Thank you for your help!
But the result that I get is different from the online crc calculator.

CRC-CCITT (0xFFFF)
0x5349

But in my code I get :

crc16_ccitt: 0xE654

What’s your idea, please?
I modified your code a little bit:

uint16_t crc16_ccitt(uint16_t* data, uint16_t data_len) {
  uint16_t crc = 0xFFFF;

  if (data_len == 0)
    return 0;

  for (unsigned int i = 0; i < data_len; ++i) {
    uint16_t dbyte = *data;
    crc ^= dbyte << 8;

    for (unsigned char j = 0; j < 8; ++j) {
      uint16_t mix = crc & 0x8000;
      crc = (crc << 1);
      if (mix)
        crc = crc ^ 0x1021;
    }
  }

  return crc;
}

void setup() {
  uint16_t test_data[4] = {1,2,3,4};
  Serial.begin(9600);
  delay(2000);
  Serial.println("***crc16_ccitt algorithm test***");
  Serial.print("Data set: ");
  for (int i = 0; i < 4; ++i) {
    Serial.print(test_data[i], DEC);
    Serial.print(", ");
 }
  Serial.print("\ncrc16_ccitt: 0x");
  Serial.print(crc16_ccitt(test_data, 4), HEX);
  Serial.println("");
}


void loop() {

}

miilado:
Sorry, I understand better now!
Thank you for your help!
But the result that I get is different from the online crc calculator.

CRC-CCITT (0xFFFF)
0x5349

But in my code I get :

crc16_ccitt: 0xE654

What’s your idea, please?
I modified your code a little bit:

uint16_t crc16_ccitt(uint16_t* data, uint16_t data_len) {

uint16_t crc = 0xFFFF;

if (data_len == 0)
   return 0;

for (unsigned int i = 0; i < data_len; ++i) {
   uint16_t dbyte = *data;
   crc ^= dbyte << 8;

for (unsigned char j = 0; j < 8; ++j) {
     uint16_t mix = crc & 0x8000;
     crc = (crc << 1);
     if (mix)
       crc = crc ^ 0x1021;
   }
 }

return crc;
}

void setup() {
 uint16_t test_data[4] = {1,2,3,4};
 Serial.begin(9600);
 delay(2000);
 Serial.println(“crc16_ccitt algorithm test”);
 Serial.print(“Data set: “);
 for (int i = 0; i < 4; ++i) {
   Serial.print(test_data[i], DEC);
   Serial.print(”, “);
}
 Serial.print(”\ncrc16_ccitt: 0x”);
 Serial.print(crc16_ccitt(test_data, 4), HEX);
 Serial.println("");
}

void loop() {

}

Kudos for working through the code provided to understand it! 8)

the error in the CRC calculation I believe is because of this line in the routine:

uint16_t dbyte = *data;

it should be:

uint16_t dbyte = data[i];

hope that helps…

sherzaad:
Kudos for working through the code provided to understand it! 8)

the error in the CRC calculation I believe is because of this line in the routine:

uint16_t dbyte = *data;

it should be:

uint16_t dbyte = data[i];

hope that helps....

Thank you, it is because of your support! :blush:
I modified it but it was not the error
I continue to work on the code and hope to find the error ...

miilado:
Thank you, it is because of your support! :blush:
I modified it but it was not the error
I continue to work on the code and hope to find the error ...

Not sure what you doing but I check the code with the fix I suggested and it return the expected value.

/*CRC-16 CCITT
    CRC 16 bits
    Polynomial 0x1021
    Initial value 0xFFFF
    No inverted input
    No inverted output
    No final XOR (0x0000)
*/
uint16_t crc16_ccitt(int16_t* data, int16_t data_len) {
  uint16_t crc = 0xFFFF;

  if (data_len == 0)
    return 0;

  for (unsigned int i = 0; i < data_len; ++i) {
    uint16_t dbyte = data[i];
    crc ^= dbyte << 8;

    for (unsigned char j = 0; j < 8; ++j) {
      uint16_t mix = crc & 0x8000;
      crc = (crc << 1);
      if (mix)
        crc = crc ^ 0x1021;
    }
  }

  return crc;
}

void setup() {
  uint16_t test_data[9] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

  Serial.begin(9600);

  Serial.println("***crc16_ccitt algorithm test***");
  Serial.print("Data set: ");
  for (int i = 0; i < 9; ++i) {
    Serial.print(test_data[i], DEC);
    Serial.print(", ");
  }
  Serial.print("\ncrc16_ccitt: 0x");
  Serial.print(crc16_ccitt(test_data, 9), HEX);
  Serial.println("");
}


void loop() {

}

Serial Monitor Output:

***crc16_ccitt algorithm test***
Data set: 49, 50, 51, 52, 53, 54, 55, 56, 57, 
crc16_ccitt: 0x29B1

CRC calculator check:

sherzaad:
Not sure what you doing but I check the code with the fix I suggested and it return the expected value.

/*CRC-16 CCITT

CRC 16 bits
   Polynomial 0x1021
   Initial value 0xFFFF
   No inverted input
   No inverted output
   No final XOR (0x0000)
/
uint16_t crc16_ccitt(int16_t
data, int16_t data_len) {
 uint16_t crc = 0xFFFF;

if (data_len == 0)
   return 0;

for (unsigned int i = 0; i < data_len; ++i) {
   uint16_t dbyte = data[i];
   crc ^= dbyte << 8;

for (unsigned char j = 0; j < 8; ++j) {
     uint16_t mix = crc & 0x8000;
     crc = (crc << 1);
     if (mix)
       crc = crc ^ 0x1021;
   }
 }

return crc;
}

void setup() {
 uint16_t test_data[9] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

Serial.begin(9600);

Serial.println("crc16_ccitt algorithm test");
 Serial.print("Data set: ");
 for (int i = 0; i < 9; ++i) {
   Serial.print(test_data[i], DEC);
   Serial.print(", ");
 }
 Serial.print("\ncrc16_ccitt: 0x");
 Serial.print(crc16_ccitt(test_data, 9), HEX);
 Serial.println("");
}

void loop() {

}




Serial Monitor Output:


crc16_ccitt algorithm test
Data set: 49, 50, 51, 52, 53, 54, 55, 56, 57,
crc16_ccitt: 0x29B1




CRC calculator check:
![Untitled.png|1366x600](upload://hdft4S6e4QBSEQG0pwPsOs2LKu8.png)

Yes, that's work Thank you ! ???

I have another issue: If I insert data in string like below code, I'll have error? Could you expalin me what will happen? I'm a little bit confused on the datatype configuration!

char test_data = "123456789";

Thank you in advance,

miilado:
I have another issue: If I insert data in string like below code, I'll have error? Could you expalin me what will happen? I'm a little bit confused on the datatype configuration!

char test_data = "123456789";

Thank you in advance,

correct syntax for a c-string would be:

char test_data[] = "123456789";

to then pass its to the crc routine, it would be:

crc16_ccitt(test_data, strlen(test_data));

hope that helps....

miilado:
Thank you for your help.
But I could not understand your method :frowning: :frowning: :frowning:

Maybe because my method uses a lookup table (much more efficient), but the lookup table is created in a way you should understand if you know how to calculate a CRC value