Results 1 to 8 of 8

Thread: CRC 16 0xA001 polynomial

  1. #1
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Question CRC 16 0xA001 polynomial

    Hi,

    I'm in need of calculating a crc 16 with 0xA001 polynomial...

    A quick glance at qChecksum shows that it uses standard CRC-16-CCITT algorithm.

    Does anyone how I can accomplish this in the same fashion of qChecksum but using the 0xA001 polynomial?

    Already thankful for any hints, code , insight,
    BR,
    Pedro Doria Meunier

  2. #2
    Join Date
    May 2006
    Location
    Warsaw
    Posts
    4
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: CRC 16 0xA001 polynomial

    Hi !

    Sample procedure
    link http://modbus.org/specs.php document Modbus_over_serial_line_V1_02.pdf

    /* Table of CRC values for high–order byte */
    static unsigned char auchCRCHi[] = {
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40
    } ;
    /* Low-Order Byte Table */
    /* Table of CRC values for low–order byte */
    static char auchCRCLo[] = {
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
    0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
    0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
    0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
    0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
    0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
    0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
    0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
    0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
    0x40
    };

    unsigned short CRC16 ( puchMsg, usDataLen ) /* The function returns the CRC as a unsigned short type */
    unsigned char *puchMsg ; /* message to calculate CRC upon */
    unsigned short usDataLen ; /* quantity of bytes in message */
    {
    unsigned char uchCRCHi = 0xFF ; /* high byte of CRC initialized */
    unsigned char uchCRCLo = 0xFF ; /* low byte of CRC initialized */
    unsigned uIndex ; /* will index into CRC lookup table */
    while (usDataLen--) /* pass through message buffer */
    {
    uIndex = uchCRCLo ^ *puchMsg++ ; /* calculate the CRC */
    uchCRCLo = uchCRCHi ^ auchCRCHi[uIndex] ;
    uchCRCHi = auchCRCLo[uIndex] ;
    }
    return (uchCRCHi << 8 | uchCRCLo) ;
    }

  3. The following user says thank you to konsie for this useful post:

    pdoria (21st October 2009)

  4. #3
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: CRC 16 0xA001 polynomial

    Thanks. But I fail to see the 0xA001 polynomial at play here...

    The truth of the matter is that I'm working with CRC's for the 1st time and I must confess I'm a complete ignorant regarding the matter...

    So the question is still open to me... how to achive the same thing (procedure wise) qDebug does but using the 0xA001 polynomial?

    Any help highly appreciated

    BR,
    Pedro Doria Meunier

  5. #4
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: CRC 16 0xA001 polynomial

    I've found this promising piece of code on the net:

    Qt Code:
    1. using System;
    2.  
    3. public class Crc16 {
    4. const ushort polynomial = 0xA001;
    5. ushort[] table = new ushort[256];
    6.  
    7. public ushort ComputeChecksum(byte[] bytes) {
    8. ushort crc = 0;
    9. for(int i = 0; i < bytes.Length; ++i) {
    10. byte index = (byte)(crc ^ bytes[i]);
    11. crc = (ushort)((crc >> 8) ^ table[index]);
    12. }
    13. return crc;
    14. }
    15.  
    16. public byte[] ComputeChecksumBytes(byte[] bytes) {
    17. ushort crc = ComputeChecksum(bytes);
    18. return new byte[] { (byte)(crc >> 8), (byte)(crc & 0x00ff) };
    19. }
    20.  
    21. public Crc16() {
    22. ushort value;
    23. ushort temp;
    24. for(ushort i = 0; i < table.Length; ++i) {
    25. value = 0;
    26. temp = i;
    27. for(byte j = 0; j < 8; ++j) {
    28. if(((value ^ temp) & 0x0001) != 0) {
    29. value = (ushort)((value >> 1) ^ polynomial);
    30. }else {
    31. value >>= 1;
    32. }
    33. temp >>= 1;
    34. }
    35. table[i] = value;
    36. }
    37. }
    38. }
    To copy to clipboard, switch view to plain text mode 

    which seems to do exactly what I want... :P

    How do I translate this to QT? please...

    BR,
    Pedro Doria Meunier

  6. The following user says thank you to pdoria for this useful post:

    DiBosco (29th May 2013)

  7. #5
    Join Date
    May 2006
    Location
    Warsaw
    Posts
    4
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: CRC 16 0xA001 polynomial

    Hi !
    First read this document Modbus_over_serial_line_V1_02.pdf
    from 39 to 43 page

    Next use this procedure

    or see
    http://libmodbus.sourceforge.net/
    http://qmodbus.sourceforge.net
    http://modbusc.sourceforge.net/
    Last edited by konsie; 21st October 2009 at 20:14.

  8. #6
    Join Date
    Sep 2009
    Location
    UK
    Posts
    2,447
    Thanks
    6
    Thanked 348 Times in 333 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: CRC 16 0xA001 polynomial

    Quote Originally Posted by pdoria View Post
    I've found this promising piece of code on the net:
    How do I translate this to QT? please...
    surely you understand that Qt is a GUI toolkit and not a language. You don't want to port it to Qt, you want to port it to C++.

  9. #7
    Join Date
    Jan 2008
    Posts
    107
    Thanks
    36
    Thanked 2 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Lightbulb [SOLVED] Re: CRC 16 0xA001 polynomial

    For anyone interested here's how I've done it:

    at global scope:

    Qt Code:
    1. static const unsigned short crc16tab[] = /* CRC lookup table [B]polynomial 0xA001[/B] */
    2. {
    3. 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
    4. 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
    5. 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
    6. 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
    7. 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
    8. 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
    9. 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
    10. 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
    11. 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
    12. 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
    13. 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
    14. 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
    15. 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
    16. 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
    17. 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
    18. 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
    19. 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
    20. 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
    21. 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
    22. 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
    23. 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
    24. 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
    25. 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
    26. 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
    27. 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
    28. 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
    29. 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
    30. 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
    31. 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
    32. 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
    33. 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
    34. 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
    35. };
    36.  
    37. #define UPDC16(ch, crc) (crc16tab[((crc) ^ (ch)) & 0xff] ^ ((crc) >> 8))
    To copy to clipboard, switch view to plain text mode 

    then just go through every byte in the array with something like this:
    Qt Code:
    1. unsigned short crc16=0;
    2. for (i=0; i< sizeof(myarray); i++) {
    3. crc16 = UPDC16( (unsigned short) myarray[i], crc16);
    4. }
    To copy to clipboard, switch view to plain text mode 

    Hope it helps someone...

    BR,
    Pedro Doria Meunier

  10. The following user says thank you to pdoria for this useful post:

    DiBosco (29th May 2013)

  11. #8
    Join Date
    Feb 2011
    Posts
    3
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11

    Default Re: CRC 16 0xA001 polynomial

    I know this is an old thread but I came upon it in my searches and then came up with a function that works well for Modbus CRC of a QByteArray

    Qt Code:
    1. uint16_t CLASS::CRC(QByteArray data) {
    2. uint16_t crc = 0xFFFF;
    3.  
    4. for(int pos = 0; pos<data.length();pos++)
    5. {
    6. crc ^= (uint16_t)data.data()[pos];
    7. for( int i = 8; i != 0; i--)
    8. {
    9. if ((crc & 0x0001) != 0) { // LSB is set
    10. crc >>= 1; // Shift right
    11. crc ^= 0xA001; // XOR 0xA001
    12. }
    13. else // LSB is not set
    14. crc >>= 1;
    15. }
    16.  
    17. }
    18. return crc;
    19. }
    To copy to clipboard, switch view to plain text mode 

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.