Can XMega CRC-CCITT be adapted for Modbus CRC?

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The XMega 16-bit CCITT polynomial generator is 0x1021, and since this cannot be changed (to my knowledge), I was wondering if the input data stream could be altered on the fly to produce a result as though the generator was using 0xA001. Thanks.

Field the chicken, ignore the ball.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't see how, and even if it can be done it probably takes just as much CPU time or more as just calculating the CRC right away in software.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm applying 0xa001 CRCs to lots of data, and due to extremely low power budget, running the XMega CPU at 500kHz. I believe the h/w CRC generator would be a great benefit to the overall message bandwidth, and was hoping some mathematical ring-theorist type could solve this. Fortunately, my Abstract Algebra days are long past... Thanks anyway.

Field the chicken, ignore the ball.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

CRC is extremely simple in hardware, especially if the data coming in is serial. Just a string of flip flops with XOR gates at selected points.

I think it wouldn't have been too difficult to make it fully configurable. Missed opportunity I guess :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The basic CRC algorithm is very simple, with some minor variations depending on which polynomial you use and if it is reflected.

You can trade memory for speed by using a lookup table. (256x16-bits for a 16-bit CRC)

uint16_t crc16( uint16_t seed, const uint8_t *buffer, uint16_t bytes )
/*
	16-bit CRC of a buffer, based on x16 x15 x2 1 (0xA001) reflected polynomial

	(Modbus, ANSI)
*/
	{
	int i;
	uint16_t crc;

	crc = seed;
	while ( ( bytes -- ) > 0 )
		{
#if defined CRC_TABLEMETHOD
		crc = ( crc >> 8 ) ^ crc_x8005r_table[ ( crc & 0x00FF ) ^ ( *buffer ++ ) ];
#else
		crc ^= *buffer ++;
		for ( i = 0; i < 8; i ++ )
			{
			if ( crc & 0x0001 )
				crc = ( crc >> 1 ) ^ 0xA001;
			else
				crc >>= 1;
			};
#endif
		};

	return crc;
	};