2

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.

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
bzc0fq
  • 579
  • 1
  • 3
  • 18
  • You need to describe in more detail what is not working. What is the test data that you are using, what should the calculated CRC be for that test data, and what is the calculated CRC that you are getting? One problem that I see is your initialization of the variable `Data16` which looks like it is supposed to be a series of hex numbers but is instead a character text string of digits and characters. So you need to check that values. I suspect it should read `unsigned char Data16[] = { 0x10, 0xac, 0x05, 0x01, 0xff };` Another question is should the `Data` parameter be the entire frame? – Richard Chambers Jul 05 '20 at 09:08
  • 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 :) – bzc0fq Jul 05 '20 at 10:11
  • That data looks to be: 01 - module address, 0B (or 11) is the frame length in bytes, 03 is the command, 01 06 87 DB C7 FF is the parameters and E5 68 is the checksum.Or is this an Answer frame with the 03 being the Answer and the FF is the operation code instead? Is the checksum supposed to be on the entire frame of all 11 bytes? – Richard Chambers Jul 05 '20 at 10:38
  • it works in this way that reader is put in automatic mode, so it sends automatically 11 bytes every time it reads a tag. CRC - this value is calculated in virtue of all the bytes except of CRCH and CRCL. – bzc0fq Jul 05 '20 at 11:04
  • Ok. makes sense. see my answer with suggested changes to your posted program. There is a change that could be made, to use the frame length - 2, `Data[1]` for the number of bytes in case the frame format should change. – Richard Chambers Jul 05 '20 at 11:07

1 Answers1

1

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
Richard Chambers
  • 16,643
  • 4
  • 81
  • 106