[SOLVED] Problem in CRC 16

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

Hai all,

   Good Day! I am using CRC16. I am new to CRC16. In this CRC initial value is 0xFFFF and polynomial is 0x8005 .

And i referred this page and i used the code. But not getting what the value is expected. i checked with online crc calculator but not getting the result.

http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html#ga95371c87f25b0a2497d9cba13190847f

 

http://www.lammertbies.nl/comm/info/crc-calculation.html

 

And my code is:

 

/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.3 Standard
Automatic Program Generator
© Copyright 1998-2011 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 4/7/2015
Author  : Dev6
Company : sass
Comments:


Chip type               : ATmega128
Program type            : Application
AVR Core Clock frequency: 14.745600 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 1024
*****************************************************/

#include <mega128.h>
#include <string.h>


#ifndef RXB8
#define RXB8 1
#endif

#ifndef TXB8
#define TXB8 0
#endif

#ifndef UPE
#define UPE 2
#endif

#ifndef DOR
#define DOR 3
#endif

#ifndef FE
#define FE 4
#endif

#ifndef UDRE
#define UDRE 5
#endif

#ifndef RXC
#define RXC 7
#endif

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART0 Receiver buffer
#define RX_BUFFER_SIZE0 256
char rx_buffer0[RX_BUFFER_SIZE0];

#if RX_BUFFER_SIZE0 <= 256
unsigned char rx_wr_index0,rx_rd_index0,rx_counter0;
#else
unsigned int rx_wr_index0,rx_rd_index0,rx_counter0;
#endif

// This flag is set on USART0 Receiver buffer overflow
bit rx_buffer_overflow0;

// USART0 Receiver interrupt service routine
interrupt [USART0_RXC] void usart0_rx_isr(void)
{
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
   rx_buffer0[rx_wr_index0++]=data;
#if RX_BUFFER_SIZE0 == 256
   // special case for receiver buffer size=256
   if (++rx_counter0 == 0) rx_buffer_overflow0=1;
#else
   if (rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;
   if (++rx_counter0 == RX_BUFFER_SIZE0)
      {
      rx_counter0=0;
      rx_buffer_overflow0=1;
      }
#endif
   }
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART0 Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter0==0);
data=rx_buffer0[rx_rd_index0++];
#if RX_BUFFER_SIZE0 != 256
if (rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0;
#endif
#asm("cli")
--rx_counter0;
#asm("sei")
return data;
}
#pragma used-
#endif

// Standard Input/Output functions
#include <stdio.h>

// Declare your global variables here


unsigned int crc16_update(unsigned int crc, unsigned char a)
{
    int i;
    crc ^= a;
    for (i = 0; i < 8; ++i)
    {
        if (crc & 1)
        crc = (crc >> 1) ^ 0x8005;
        else
        crc = (crc >> 1);
    }
    return crc;
}


void main(void)
{
// Declare your local variables here

        unsigned char arr[] = "123456789";
        unsigned int i =0;
        unsigned int crc = 0xffff;


// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Port E initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTE=0x00;
DDRE=0x00;

// Port F initialization
// Func7=In Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=In
// State7=T State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=T
PORTF=0x00;
DDRF=0x7E;

// Port G initialization
// Func4=In Func3=In Func2=In Func1=In Func0=In
// State4=T State3=T State2=T State1=T State0=T
PORTG=0x00;
DDRG=0x00;

// USART0 initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART0 Receiver: On
// USART0 Transmitter: On
// USART0 Mode: Asynchronous
// USART0 Baud Rate: 9600
UCSR0A=0x00;
UCSR0B=0x98;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x5F;

// Global enable interrupts
#asm("sei")

puts("\nstart");


for(i =0; i<strlen(arr); ++i)
{
   crc = crc16_update(crc, arr[i]);
//   printf("\ncrc1 = %d", crc);
}
printf("\ncrc = 0x%x", crc);

puts("\nend");

while (1)
      {

      }
}

And output i am getting is

 start

                                                       crc = 0x3d7b
                                                                   end

 

Expected output is 

0xBB3D

 

I dont know where the problem is. Can you please suggest me where the problem is?

 

This topic has a solution.

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

Last Edited: Tue. Apr 21, 2015 - 09:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Take a look at this recent thread: https://www.avrfreaks.net/forum/c...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Augmentation ?

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

yes awneil. i gone through it but not getting.

And also i read the http://www.barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code

And i tried this also.

/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.3 Standard
Automatic Program Generator
© Copyright 1998-2011 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 4/9/2015
Author  : Dev6
Company : sass
Comments:


Chip type               : ATmega128
Program type            : Application
AVR Core Clock frequency: 14.745600 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 1024
*****************************************************/

#include <mega128.h>
#include <stdio.h>
#include <string.h>



#define WIDTH  16    //(8 * sizeof(unsigned char))
#define TOPBIT (1 << (WIDTH - 1))
#define POLYNOMIAL 0x8005

unsigned char crcTable[256];

#ifndef RXB8
#define RXB8 1
#endif

#ifndef TXB8
#define TXB8 0
#endif

#ifndef UPE
#define UPE 2
#endif

#ifndef DOR
#define DOR 3
#endif

#ifndef FE
#define FE 4
#endif

#ifndef UDRE
#define UDRE 5
#endif

#ifndef RXC
#define RXC 7
#endif

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART0 Receiver buffer
#define RX_BUFFER_SIZE0 256
char rx_buffer0[RX_BUFFER_SIZE0];

#if RX_BUFFER_SIZE0 <= 256
unsigned char rx_wr_index0,rx_rd_index0,rx_counter0;
#else
unsigned int rx_wr_index0,rx_rd_index0,rx_counter0;
#endif

// This flag is set on USART0 Receiver buffer overflow
bit rx_buffer_overflow0;

// USART0 Receiver interrupt service routine
interrupt [USART0_RXC] void usart0_rx_isr(void)
{
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
   rx_buffer0[rx_wr_index0++]=data;
#if RX_BUFFER_SIZE0 == 256
   // special case for receiver buffer size=256
   if (++rx_counter0 == 0) rx_buffer_overflow0=1;
#else
   if (rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;
   if (++rx_counter0 == RX_BUFFER_SIZE0)
      {
      rx_counter0=0;
      rx_buffer_overflow0=1;
      }
#endif
   }
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART0 Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter0==0);
data=rx_buffer0[rx_rd_index0++];
#if RX_BUFFER_SIZE0 != 256
if (rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0;
#endif
#asm("cli")
--rx_counter0;
#asm("sei")
return data;
}
#pragma used-
#endif



void crcInit(void)
{
    unsigned int  remainder;
    unsigned int dividend = 0;
    unsigned char b;

    printf("\nwidth: %d", WIDTH);
    /*
     * Compute the remainder of each possible dividend.
     */
    for (dividend = 0; dividend < 256; ++dividend)
    {
        /*
         * Start with the dividend followed by zeros.
         */
        remainder = dividend << (WIDTH - 8);

        /*
         * Perform modulo-2 division, a bit at a time.
         */
        for (b = 8; b > 0; --b)
        {
            /*
             * Try to divide the current data bit.
             */
            if (remainder & TOPBIT)
            {
                remainder = (remainder << 1) ^ POLYNOMIAL;
            }
            else
            {
                remainder = (remainder << 1);
            }
        }

        /*
         * Store the result into the table.
         */
        crcTable[dividend] = remainder;
    }

}   /* crcInit() */

unsigned char crcFast(unsigned char const message[], unsigned int nBytes)
{
    unsigned char data;
    unsigned char remainder = 0;
    unsigned int byte = 0;


    /*
     * Divide the message by the polynomial, a byte at a time.
     */
    for (byte = 0; byte < nBytes; ++byte)
    {
        data = message[byte] ^ (remainder >> (WIDTH - 8));
        remainder = crcTable[data] ^ (remainder << 8);
    }

    printf("\nremainder: 0x%X", remainder);

    /*
     * The final remainder is the CRC.
     */
    return (remainder);

}   /* crcFast() */

void main(void)
{
// Declare your local variables here

unsigned char checksum;
unsigned char arr[] = "123456789";

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;

// Port E initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTE=0x00;
DDRE=0x00;

// Port F initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTF=0x00;
DDRF=0x00;

// Port G initialization
// Func4=In Func3=In Func2=In Func1=In Func0=In
// State4=T State3=T State2=T State1=T State0=T
PORTG=0x00;
DDRG=0x00;

// USART0 initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART0 Receiver: On
// USART0 Transmitter: On
// USART0 Mode: Asynchronous
// USART0 Baud Rate: 9600
UCSR0A=0x00;
UCSR0B=0x98;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x5F;

// Global enable interrupts
#asm("sei")

puts("\nStart");

crcInit();

checksum = crcFast(arr, strlen(arr));
printf("\nl: %d", strlen(arr));
//printf("\nlength: %d", sizeof(arr));
printf("\nchecksum: 0x%X", checksum);

puts("\nEnd");

while (1)
      {
      // Place your code here

      }
}

output is:

 

 Start

                                                     width: 16
                                                              remainder: 0x96
                                                                             l:
9
 checksum: 0x96
               End

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

Last Edited: Thu. Apr 9, 2015 - 11:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

The software used on that website is presumably this:

 

http://www.lammertbies.nl/downlo...

 

Fom that the bits relevant to crc16 would appear to be:

#define                 P_16        0xA001

static int              crc_tab16_init          = FALSE;

static unsigned short   crc_tab16[256];

static void init_crc16_tab( void ) {

    int i, j;
    unsigned short crc, c;

    for (i=0; i<256; i++) {

        crc = 0;
        c   = (unsigned short) i;

        for (j=0; j<8; j++) {

            if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_16;
            else                      crc =   crc >> 1;

            c = c >> 1;
        }

        crc_tab16[i] = crc;
    }

    crc_tab16_init = TRUE;

}  /* init_crc16_tab */

unsigned short update_crc_16( unsigned short crc, char c ) {

    unsigned short tmp, short_c;

    short_c = 0x00ff & (unsigned short) c;

    if ( ! crc_tab16_init ) init_crc16_tab();

    tmp =  crc       ^ short_c;
    crc = (crc >> 8) ^ crc_tab16[ tmp & 0xff ];

    return crc;

}  /* update_crc_16 */

So why not try that in your AVR rather than the code you currently have?

 

Anyway this sort of proves a point. When using CRCs there's often so many "variants" that the only important thing is that both ends use the exact same algorithm. Just saying CRC16 with polynomial XXXX is often not enough to fully identify any variant.

 

BTW I cannot help but notice that you use 0x8005 and they use P_16 == 0xA001.

 

So perhaps for starters see what you get if you change from 8005 to A001. What made you think 0x8005 was the right polynomial to use in the first place?

 

EDIT: Oh right, I see, they have a table of "common polynomials" at the bottom of that online calculator page. However just because they say 8005 is common does not necessarily mean it's what they use.

Last Edited: Thu. Apr 9, 2015 - 12:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks a lot clawson. I tried your code.

In this for 0xA001 output is  0x4b37

for 0x8005  output is 0x3d7b

 

not getting the expected value

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

Last Edited: Thu. Apr 9, 2015 - 01:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Well I tried to see the source they were using for their web page app. I hoped it would be in Javascript and readable. But it is implemented as a PHP application so it's not easy to access their source.

 

My guess is that the web page is doing something different to their library code.

 

Given that they have a support forum I would use it to ask them exactly how the CRC16 in the web app is being calculated.

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

Okay clawson. Thanks  a lot for great help :)

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

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

as others have said there are many ways to init and calc, and one that haven't been told here is that the CRC often are made/placed, so the receiver make CRC of the hole block incl CRC and then should get 0 (or ffff), I can't remember how the two CRC are connected, so which is the one you try to get the same result as?  

Last Edited: Thu. Apr 9, 2015 - 01:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

OK well just to check the code they supply I built it (having created a CMakeLists.txt):

$ cat CMakeLists.txt 
project("crc")

set(CRCLIB_SRC
	lib_crc.c
)

add_library(crc STATIC ${CRCLIB_SRC})

set(TEST_SRC
	tst_crc.c
)

add_executable(test ${TEST_SRC})
target_link_libraries(test crc)

$ cmake .
-- The C compiler identification is GNU 4.8.1
-- The CXX compiler identification is GNU 4.8.1
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/uid23021/lib_crc

$ make
Scanning dependencies of target crc
[ 50%] Building C object CMakeFiles/crc.dir/lib_crc.c.o
Linking C static library libcrc.a
[ 50%] Built target crc
Scanning dependencies of target test
[100%] Building C object CMakeFiles/test.dir/tst_crc.c.o
Linking C executable test
[100%] Built target test

uid23021@lxl0131u:~/lib_crc$ ./test -a

CRC algorithm sample program
Lammert Bies,  Version 1.16

Input: 123456789
"123456789" :
CRC16              = 0xBB3D      /  47933
CRC16 (Modbus)     = 0x4B37      /  19255
CRC16 (Sick)       = 0x56A6      /  22182
CRC-CCITT (0x0000) = 0x31C3      /  12739
CRC-CCITT (0xffff) = 0x29B1      /  10673
CRC-CCITT (0x1d0f) = 0xE5CC      /  58828
CRC-CCITT (Kermit) = 0x8921      /  35105
CRC-DNP            = 0x82EA      /  33514
CRC32              = 0xCBF43926  /  3421780262

That does seem to confirm that when I enter 123456789[Enter] I get the expected 0xBB3D.

 

If you don't get the same result it's almost certainly because of a difference in sizeof(int). Try replacing any "int" in there code with "uint32_t" and #include <stdint.h> and see what happens. (the PC software will be using 32 bits for int).

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

Hai clawson,

   Good Day! I am not getting your point. i am  very very sorry. can you please explain one more time please.

 

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

Last Edited: Fri. Apr 10, 2015 - 05:35 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hi clawson,

   in OP  code i changed polynomial value as 0xA001 and initial crc as 0x0000 and now i am getting the result as 0xBB3D.

But in online calculator the used polynomial value as 0x8005 for this 0x8005 polynomial result is 0xBB3D. i am getting confusing which one is correct.

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

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

it's the same poly. 

just MSB first or last

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

yes it is okay. why it should be like that.  really i am getting confused why it is reversed.  please 

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

Last Edited: Fri. Apr 10, 2015 - 08:09 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I can't remember, (but I guess you can google it).

But in general CRC can be done in many ways, and because it's based on modulus it's legal to cheat on the division to speed it up

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

Did you follow Andy's advice in post #2 ?

 

If you did you would have reached here:

 

http://en.wikipedia.org/wiki/Cyc...

 

As you then read here:

 

http://en.wikipedia.org/wiki/Cyc...

 

So there can be many variants for one polynomial.

 

Also my point above was that their web software and their library are likely designed for 32/64 bit CPUs. As I showed you, when I took their software package and built it for a 64 bit CPU I got the expected BB3D result. If you are saying that you took exactly that same software, built it for an AVR and then did no get BB3D a very likely reason is the difference in sizeof(int) and some kind of "integer overflow" effect you may be seeing on the AVR that was not evident in the PC build (where sizeof(int)==4 not 2).

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

I can recommend the CRC16 tool in a recent contribution, see https://www.avrfreaks.net/forum/i-duplicate-work-someone-else-has-done?skey=crc16tool

I modified the code a little for easier use, and can provide it if needed

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

yes okay. Thanks a lot. i will google it.

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

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

yes Okay clawson. I read it. Again i will read it one more time to get it clear. If any doubt after reading it i will ask you. thanks a lot clawson.

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

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

Yes jerry. i have downloaded the zip file. in that .exe is not running.

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

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

yes clawson i got it.

 

i referred this link also

http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks#Bit_ordering_.28Endianness.29

 

And i tried with normal polynomial 0x8005 and i am getting result as 0xFEE8

Then i checked this link. in this link after un click reverse data bytes and reverse CRC result before final XOR, i am getting the result as 0xFEEB. 

how to do these two steps

step 1: reverse data bytes

step 2: reverse CRC result before final XOR 

http://www.zorc.breitbandkatze.de/crc.html

 

code is


unsigned int crc16_update_big_endian(unsigned int crc, unsigned char a)
{
    // Most significant bit first (big-endian)
    // x^16+x^15+x^2+1 = (1) 1000 0000 0000 0101 = 0x8005   (CRC 16 POLYNOMIAL)

    unsigned int i,n=16;
    crc ^=(a << (n-8));

    for (i = 0; i < 8; ++i)     // Assuming 8 bits per byte
    {
        if (crc & 0x8000)  // if leftmost (most significant) bit is set
        {
            crc = (crc << 1) ^ 0x8005;
        }
        else
        {
            crc = (crc << 1);
        }
        crc = crc & 0xffff;      // Trim remainder to 16 bits
    }
    return crc;
}

void main(void)
{
    unsigned char arr[] = "123456789";
    unsigned int i =0;
    unsigned int crc0 = 0x0000;

    puts("\nstart");

    for(i =0; i<strlen(arr); ++i)
    {
       crc0 = crc16_update_big_endian(crc0, arr[i]);
    }
    printf("\ncrc1 = 0x%X", crc0);

    puts("\nend");

}

 

 

 

 

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

Last Edited: Sat. Apr 11, 2015 - 04:24 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Why are you making your posts almost impossible to read?

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

CRC is traditionally taken LSB first, since it was developed for serial communications protocols that transmit LSB first. They work in both directions, but give different answers. What catches out most people is that if you're calculating it the usual way, LSB first, the polynomial has to be bit reversed in the algorithm. Try using 0xA001 in your software and see if that works.

 

Here's an algorithm I prefer - it's for CCITT16 and it's really fast because it does it a byte at a time, not a bit at a time (note the *data, n is the number of bytes not the number of bits). Unfortunately it's tailored to the CCITT poly and won't work for the IBM CRC16, because creating the magic number loses significant bits of the CRC16 poly.

 

unsigned calc_crc(unsigned char *data, unsigned n, unsigned start) {
    unsigned I, k, q, c, crcval;
    crcval=start;
    for (I=0; I<n; I++) {
            c=data(I) & 0xFF;
            q=(crcval^c) & 0x0F;
            crcval=(crcval>>4)^(q*0x1081);
            q=(crcval^(c>>4)) & 0x0F;
            crcval=(crcval>>4)^(q*0x1081);
        }
    return crcval;
}

The magic number 1081 was derived as follows.

The CCITT polynomial is X16 + X12 + X5 +1

Writing that in binary, it is 1_0001_0000_0010_0001, or 0x1021 dropping the MSB.

That is then bit reversed, giving 1000_0100_0000_1000_1, including the MSB

The whole 17 bit number is then shifted 4 places to the right, thus:

    0_0001_0000_1000_0001

shifting in zeros and dropping off the four LS bits (0001)

 

This can be done for CCITT because the X16 bit is the only '1' lost in the shift.

 

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

Hai clawson, 

    Good day! very very sorry for troubles. now i edited the post.

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

Last Edited: Sat. Apr 11, 2015 - 04:25 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hai peret,

 

   Thanks a lot. I got it.

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN

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

Hai all,

   Thanks a lot  to all for given wonderful ,valuable and very clear  points about CRC. Thanks to awneil , clawson , sparrow2 , jerryr , peret .

-----------------------

Thanks & Regards,

Sasi

-----------------------

GO GREEN