bzc0fq
bzc0fq

Reputation: 719

CRC16 CCITT code - how to adapt manufacturer sample source

I try to create a code that would read data from RFID reader module. In order to do this I need to do CRC16 CCITT calculation.

I have found C source code for the CRC16 checksum calculation in the reader manufacturer application technical datasheet http://www.card-sys.com/manuals/framer_eng.pdf

Unfortunately this is just a part of code not a full working example.

When the RFID reader is put in automatic mode, it automatically sends 11 bytes every time it reads a tag. CRC - this value is calculated using all of the bytes except the last two bytes which are the CRCH (CRC high byte) and CRCL (CRC low byte).

When I read RFID tag from a reader I got 11 bytes transferred... i.e. (hex) 01 0B 03 01 06 87 DB C7 FF E5 68. Last two bytes E5 68 are the CRC16 checksum for the message. In order to confirm the data is OK I need to calculate the same CRC16 against 01 0B 03 01 06 87 DB C7 FF at the destination point.

I tried putting everything together in one piece, but I do not have much experience with C programing and my code does not work.

Here is the source code:

#include <stdio.h>
#include <stdlib.h>

// CRC16 from Netronix datasheet
void CRC16(unsigned char * Data, unsigned short * CRC, unsigned char Bytes)
    {
        int i, byte;
        unsigned short C;

        *CRC = 0;
        for (byte = 1; byte <= Bytes; byte ++, Data ++)
            {
                C = ((*CRC >> 8) ^ *Data) << 8;
                for (i = 0; i < 8; i ++)
                    {
                        if (C & 0x8000)
                            C = (C << 1) ^ 0x1021;
                        else
                            C = C << 1;
                    }
                *CRC = C ^ (*CRC << 8);
            }
    }


int main(void)
    {
        puts("Test...");

        unsigned char * Data16="10ac0501ff";
        unsigned short * CRC=0;
        unsigned char Bytes16=4;

        CRC16(Data16,CRC,Bytes16);

        puts(CRC);

        return EXIT_SUCCESS;
    }

What I would like to do is learn how to use manufacturer code in working example - means how to get crc16 calculated.

Could you please help me with this? Thanks.

Upvotes: 2

Views: 2273

Answers (1)

Richard Chambers
Richard Chambers

Reputation: 17593

Using your source code I created the following program.

#include <stdio.h>
#include <stdlib.h>

// CRC16 from Netronix datasheet
void CRC16(unsigned char * Data, unsigned short * CRC, unsigned char Bytes)
{
    int i, byte;
    unsigned short C;

    *CRC = 0;
    for (byte = 1; byte <= Bytes; byte++, Data++)
    {
        C = ((*CRC >> 8) ^ *Data) << 8;
        for (i = 0; i < 8; i++)
        {
            if (C & 0x8000)
                C = (C << 1) ^ 0x1021;
            else
                C = C << 1;
        }
        *CRC = C ^ (*CRC << 8);
    }
}


int main(void)
{

    // When I read RFID tag from a reader I got 11 bytes transferred... i.e.
    // (hex)01 0B 03 01 06 87 DB C7 FF E5 68.
    // Last two bytes E5 68 are crc16.
    // In order to confirm the data is OK I need to calculate the same crc16
    // against 01 0B 03 01 06 87 DB C7 FF at the destination point.
    unsigned char  Data16[] = { 0x01, 0x0B, 0x03, 0x01, 0x06, 0x87, 0xDB, 0xC7, 0xFF };
    unsigned short CRC = 0;
    unsigned char Bytes16 = 9;

    CRC16(Data16, &CRC, Bytes16);

    printf(" CRC calculated is %x\n", CRC);

    return EXIT_SUCCESS;
}

The output is CRC calculated is e568.

There are a couple of changes I made.

First is the data I used which is from your comment on the RFID tag reader output.

When I read RFID tag from a reader I got 11 bytes transferred... i.e. (hex) 01 0B 03 01 06 87 DB C7 FF E5 68. Last two bytes E5 68 are crc16. In order to confirm the data is OK I need to calculate the same crc16 against 01 0B 03 01 06 87 DB C7 FF at the destination point. You are probably right about the Data16[]... I will change this later today and let you know what current status is. Thanks for helping :)

I used a length of the data that excludes the checksum. So the length in the frame data is 0x0B or 11 and since the checksum is 2 bytes, I used 11 - 2 or 9 for the length.

Finally I changed the definition of the variable CRC to unsigned short CRC = 0; and when calling the CRC function, I used the address of operator as in CRC16(Data16, &CRC, Bytes16);.

Frame format for serial transmission

From the documentation you referenced there are two types of frames or messages whose formats are as follows:

Command frame:

  • module address (1 byte) unique address of each module in network
  • frame length (1 byte) full length of frame (includes 2 byte checksum)
  • command (1 byte) command code which is an even value
  • parameters (variable length) optional parameters depending on command
  • CRCH (1 byte) upper byte of the CRC16
  • CRCL (1 byte) lower byte of the CRC16

Answer frame:

  • module address (1 byte) unique address of each module in network
  • frame length (1 byte) full length of frame (includes 2 byte checksum)
  • answer(1 byte) answer code which is an odd value
  • parameters (variable length) optional parameters depending on command
  • operation code (1 byte) command execution status
  • CRCH (1 byte) upper byte of the CRC16
  • CRCL (1 byte) lower byte of the CRC16

Upvotes: 1

Related Questions