Page 1 of 1

Generating a CRC

Posted: Fri Feb 22, 2008 1:49 am
by Jeff Barnes
Hi Everyone,

I am trying to connect to a patient monitor to extract data.
The monitor has an ASCII protocol the requires a CRC as part of the command request.

For example, If I want to issue a "Connect" command I would need to do the following:

Format: Header <command> CRC

so the actual command to send is: DIAP000<connect>CRC

In the manual they have a small section on the CRC that I just do not understand.

From the manual:

CRC Algorithm

The algorithm used to create the CRC follows:

const unsigned short crcTable[256] = {

0x0000, 0x0108, 0x0210, 0x0318, 0x0420, 0x0528, 0x0630, 0x0738,

0x0840, 0x0948, 0x0A50, 0x0B58, 0x0C60, 0x0D68, 0x0E70, 0x0F78,

0x1081, 0x1189, 0x1291, 0x1399, 0x14A1, 0x15A9, 0x16B1, 0x17B9,

0x18C1, 0x19C9, 0x1AD1, 0x1BD9, 0x1CE1, 0x1DE9, 0x1EF1, 0x1FF9,

0x2102, 0x200A, 0x2312, 0x221A, 0x2522, 0x242A, 0x2732, 0x263A,

0x2942, 0x284A, 0x2B52, 0x2A5A, 0x2D62, 0x2C6A, 0x2F72, 0x2E7A,

0x3183, 0x308B, 0x3393, 0x329B, 0x35A3, 0x34AB, 0x37B3, 0x36BB,

0x39C3, 0x38CB, 0x3BD3, 0x3ADB, 0x3DE3, 0x3CEB, 0x3FF3, 0x3EFB,

0x4204, 0x430C, 0x4014, 0x411C, 0x4624, 0x472C, 0x4434, 0x453C,

0x4A44, 0x4B4C, 0x4854, 0x495C, 0x4E64, 0x4F6C, 0x4C74, 0x4D7C,

0x5285, 0x538D, 0x5095, 0x519D, 0x56A5, 0x57AD, 0x54B5, 0x55BD,

0x5AC5, 0x5BCD, 0x58D5, 0x59DD, 0x5EE5, 0x5FED, 0x5CF5, 0x5DFD,

0x6306, 0x620E, 0x6116, 0x601E, 0x6726, 0x662E, 0x6536, 0x643E,

0x6B46, 0x6A4E, 0x6956, 0x685E, 0x6F66, 0x6E6E, 0x6D76, 0x6C7E,

0x7387, 0x728F, 0x7197, 0x709F, 0x77A7, 0x76AF, 0x75B7, 0x74BF,

0x7BC7, 0x7ACF, 0x79D7, 0x78DF, 0x7FE7, 0x7EEF, 0x7DF7, 0x7CFF,

0x8408, 0x8500, 0x8618, 0x8710, 0x8028, 0x8120, 0x8238, 0x8330,

0x8C48, 0x8D40, 0x8E58, 0x8F50, 0x8868, 0x8960, 0x8A78, 0x8B70,

0x9489, 0x9581, 0x9699, 0x9791, 0x90A9, 0x91A1, 0x92B9, 0x93B1,

0x9CC9, 0x9DC1, 0x9ED9, 0x9FD1, 0x98E9, 0x99E1, 0x9AF9, 0x9BF1,

0xA50A, 0xA402, 0xA71A, 0xA612, 0xA12A, 0xA022, 0xA33A, 0xA232,

0xAD4A, 0xAC42, 0xAF5A, 0xAE52, 0xA96A, 0xA862, 0xAB7A, 0xAA72,

0xB58B, 0xB483, 0xB79B, 0xB693, 0xB1AB, 0xB0A3, 0xB3BB, 0xB2B3,

0xBDCB, 0xBCC3, 0xBFDB, 0xBED3, 0xB9EB, 0xB8E3, 0xBBFB, 0xBAF3,

0xC60C, 0xC704, 0xC41C, 0xC514, 0xC22C, 0xC324, 0xC03C, 0xC134,

0xCE4C, 0xCF44, 0xCC5C, 0xCD54, 0xCA6C, 0xCB64, 0xC87C, 0xC974,

0xD68D, 0xD785, 0xD49D, 0xD595, 0xD2AD, 0xD3A5, 0xD0BD, 0xD1B5,

0xDECD, 0xDFC5, 0xDCDD, 0xDDD5, 0xDAED, 0xDBE5, 0xD8FD, 0xD9F5,

0xE70E, 0xE606, 0xE51E, 0xE416, 0xE32E, 0xE226, 0xE13E, 0xE036,

0xEF4E, 0xEE46, 0xED5E, 0xEC56, 0xEB6E, 0xEA66, 0xE97E, 0xE876,

0xF78F, 0xF687, 0xF59F, 0xF497, 0xF3AF, 0xF2A7, 0xF1BF, 0xF0B7,

0xFFCF, 0xFEC7, 0xFDDF, 0xFCD7, 0xFBEF, 0xFAE7, 0xF9FF, 0xF8F7,

};

unsigned short Crc (unsigned short lastCrc, unsigned long sizeOfBuffer,

unsigned char *buffer) {

unsigned long i;

unsigned char index;

for (i = 0L; i < sizeOfBuffer; i++) {

index = buffer ^ ((unsigned char)(lastCrc & 0x00FF));

lastCrc = ((lastCrc >> 8) & 0x00FF) ^ (crcTable[index]);

}

return (lastCrc);

}



CRC Test Program

The following program can be used to test the above:

#include <stdio.h>

int main(void) {

unsigned char buffer [] = {0, 0, 0, 0, 0, 0x77, 0xCF};

printf(“CRC(Expected 0x73F3) = 0x%04X\n”, Crc(0x0, 7, buffer));

return(0);

}

NOTE: For the example above, the value for the last CRC

parameter should be initalized to zero (0).







Can anyone help me to understand this and point me in the right direction?



Thanks in advance,

Re: Generating a CRC

Posted: Fri Feb 22, 2008 7:49 am
by Enrico Maria Giordano
Try using HB_CRC32().

EMG

Posted: Fri Feb 22, 2008 9:38 am
by Antonio Linares
Jeff,

FWH provides:

nFileCRC( cFileName ) --> nCRC

nStrCRC( cString ) --> nCRC

Posted: Fri Feb 22, 2008 2:31 pm
by Jeff Barnes
Enrico/Antonio,

The problem is that the CRC can only be a 4 char hex string.

Here is an example of the error codes returned with their correct CRC values:

DIAP000<%REQUEST CORRUPT>734D

DIAP000<%INVALID CRC CHAR>A471


I am just so lost on this one. I have send an email to the manufacturer of the device but I have no idea when they will reply and I need to provide an answer to end user today.

Any help you can provide will be greatly appreciated.

Posted: Fri Feb 22, 2008 5:52 pm
by Antonio Linares
Jeff,

You can use FWH DecToHex():

DecToHex( nFileCRC( cFileName ) )

DecToHex( nStrCRC( cString ) )

Posted: Fri Feb 22, 2008 7:09 pm
by Jeff Barnes
Hi Antonio,

I've tried with the DecToHex() but still end up with an 8 char Hex number instead of the needed 4 char hex number as in the example below:


Header <command> CRC

DIAP000<%REQUEST CORRUPT>734D

DIAP000<%INVALID CRC CHAR>A471


I still have not had a reply from the manufacturer :-(

Posted: Fri Feb 22, 2008 8:25 pm
by Antonio Linares
Jeff,

A hex number of four characters can hold a number <= 65535

So if the number is larger than 65535 (FFFF) then you can not use four characters only.

Posted: Fri Feb 22, 2008 8:49 pm
by Jeff Barnes
I have written a small app that will send the command with 0000 to FFFF and see what CRC works. It is going to take a while but I can not figure out how they generate this 4 char hex either.

Thanks for the effort ... You know they will finally get back to me after it has been figured out :-)

Posted: Fri Feb 22, 2008 9:45 pm
by Enrico Maria Giordano
Maybe you'd need of a CRC16 function.

EMG

Posted: Fri Feb 22, 2008 11:42 pm
by Jeff Barnes
Is there a CRC16 function?

Posted: Sat Feb 23, 2008 11:24 am
by Enrico Maria Giordano
This is a function I used with Clipper long time ago:

Code: Select all

#include "extend.h"


CLIPPER crc16()
{
    char *s = _parc( 1 );
    int crc = 0;
    int i, j;

    for ( i = 0; i < 128; i++ )
    {
        crc ^= *s++ << 8;

        for ( j = 0; j < 8; j++ )
            if ( crc & 0x8000 )
                crc = ( crc << 1 ) ^ 0x1021;
            else
                crc = crc << 1;
    }

    _retni( crc );
}
EMG

Posted: Sat Feb 23, 2008 11:26 am
by Enrico Maria Giordano
The fixed value of 128 has to be calculated using strlen() instead.

EMG