CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to

CRC16, very efficient
Goto page Previous  1, 2
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message

Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Nov 16, 2012 5:27 pm     Reply with quote

While trying to understand the code I found I could replace the two rlcf with one rlncf on a PIC18.
Nice find!
I have updated my code at the start of this topic to include this improvement.

Joined: 18 Nov 2012
Posts: 1

View user's profile Send private message

Poly change impossible?
PostPosted: Mon Nov 19, 2012 2:50 am     Reply with quote

I have found this discussion with very elegant solution for CRC16 for embedded projects.
I would change poly to CRC16-ARC - 0x8005.

I think it should be for 0x8005:
crc = (crc << 8) ^ (x << 15) ^ (x << 2) ^ x;

instead of 0x1021
crc = (crc << 8) ^ (x << 12) ^ (x << 5) ^ x;

Additionally original CRC16-ARC starts from crc=0x0000 and needs bits reflecting in input bytes and reflecting crc bits on output (0b11010010 -> 0b01001011).

I have a set of W. Erhardt applications (SRP, TCRC) as a reference calculations but I can't get proper CRC with this algorithm after poly change.

I have written small app in Delphi using code presented here and I have got same results like in PIC18 environment - good CRC calculations for 0x1021 and bad calculations for 0x8005 poly. To do bits reflecting I have used functions copied from W. Erhardt applications.

My mistakes or ..... algorithm for 0x1021 only? - I do not want to believe..

Any ideas?


One hour later...
I have repeated some steps of my discovering and now I have found notice from the Ashley Roll:

* I've used the Standard CCITT CRC16 polynomial as this "standard"
* doesn't use any of the bit reflection that confuses the implementation.
* This polynomial is 0x1021 but you could use any you like.

Full text is here:
So it means that when bits are reflecting something can go wrong.

Looking for another solutions I have found:

There are some Pascal examples of table and non-table CRC calculations.
I have checked immediately function CRC16 bit, inverted/reversed/reflected and I have got good result.

I have translated it to C and it works in PIC18F environment as well Smile

Here is the final, not optimized yet code:

unsigned int Calc_CRC_C_ARC(unsigned char *Buffer, unsigned int  Len, unsigned int crc_seed)
   crc = crc_seed;
      bufdat = *Buffer++;
      crc = crc ^ bufdat;
     for (i = 0;i < 8; i++)
        if ((crc & 0x0001) !=0)
// Expected poly should be bits reflected so 0xA001 used instead of 0x8005;
           crc = (crc >> 1) ^ 0xA001;
           crc = crc >> 1;
//   Swapping final CRC nibbles
   crc = (crc >> 8) | (crc << 8);
   printf("CRC ARC: Seed: %.4x; Val: %.4x\r\n",crc_seed, crc);
   return crc;

Now I will optimize the code and check if this is fast enough for me, if not I will go to assembler.
I hope that it can be useful for somebody Smile


Joined: 18 Oct 2017
Posts: 1

View user's profile Send private message

PostPosted: Wed Oct 18, 2017 7:57 am     Reply with quote

I have used this code to determine the crc16 for a PIC 24FJ128GA204.h
but it get the false crc. Can anybody tell me what's wrong ?

int16 crc_1021(int16 old_crc, int8 data)
    int16 crc;
    int16 x;

    x = make8(old_crc,1) ^ data;  //x = ((old_crc>>8) ^ data) & 0xff;
    x ^= x>>4;

    crc = (old_crc << 8) ^ (x << 12) ^ (x <<5) ^ x;
  //crc &= 0xffff;

    return crc;

I want to build the crc of this char '*'

const int16 CRC_startwert=0xffff

         CRC_Calc_X = CRC_startwert;
         CRC_Calc_X = crc_1021(CRC_Calc_X,'*');

PCM programmer

Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Oct 19, 2017 10:16 am     Reply with quote

That routine is written for the PCM and/or PCH compilers. In those
compilers, the default for integer data types is unsigned.
However, in the PCD compiler (which you have), the default is signed.

So I suggest that you change all variable declarations in the CRC routine
and in your program to 'unsigned'. Then it has a chance to work.

unsigned int16 crc_1021(unsigned int16 old_crc, unsigned int8 data)
unsigned int16 crc;
unsigned int16 x;

And do it everywhere else where there is a variable declaration.

Edit: Dawel reports in a PM that this has resolved his problem.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Powered by phpBB © 2001, 2005 phpBB Group