www.pudn.com > lib_crc_16-32.zip > lib_crc.c


#include "lib_crc.h" 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   Library         : lib_crc                                       * 
    *   File            : lib_crc.c                                     * 
    *   Author          : Lammert Bies  1999-2007                       * 
    *   E-mail          : info@lammertbies.nl                           * 
    *   Language        : ANSI C                                        * 
    *                                                                   * 
    *                                                                   * 
    *   Description                                                     * 
    *   ===========                                                     * 
    *                                                                   * 
    *   The file lib_crc.c contains the private  and  public  func-     * 
    *   tions  used  for  the  calculation of CRC-16, CRC-CCITT and     * 
    *   CRC-32 cyclic redundancy values.                                * 
    *                                                                   * 
    *                                                                   * 
    *   Dependencies                                                    * 
    *   ============                                                    * 
    *                                                                   * 
    *   lib_crc.h       CRC definitions and prototypes                  * 
    *                                                                   * 
    *                                                                   * 
    *   Modification history                                            * 
    *   ====================                                            * 
    *                                                                   * 
    *   Date        Version Comment                                     * 
    *                                                                   * 
    *   2007-04-01  1.15    Added CRC16 calculation for Modbus          * 
    *                                                                   * 
    *   2007-03-28  1.14    Added CRC16 routine for Sick devices        * 
    *                                                                   * 
    *   2005-12-17  1.13    Added CRC-CCITT with initial 0x1D0F         * 
    *                                                                   * 
    *   2005-05-14  1.12    Added CRC-CCITT with start value 0          * 
    *                                                                   * 
    *   2005-02-05  1.11    Fixed bug in CRC-DNP routine                * 
    *                                                                   * 
    *   2005-02-04  1.10    Added CRC-DNP routines                      * 
    *                                                                   * 
    *   1999-02-21  1.01    Added FALSE and TRUE mnemonics              * 
    *                                                                   * 
    *   1999-01-22  1.00    Initial source                              * 
    *                                                                   * 
    \*******************************************************************/ 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   #define P_xxxx                                                  * 
    *                                                                   * 
    *   The CRC's are computed using polynomials. The  coefficients     * 
    *   for the algorithms are defined by the following constants.      * 
    *                                                                   * 
    \*******************************************************************/ 
 
#define                 P_16        0xA001 
#define                 P_32        0xEDB88320L 
#define                 P_CCITT     0x1021 
#define                 P_DNP       0xA6BC 
#define                 P_SICK      0x8005 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   static int crc_tab...init                                       * 
    *   static unsigned ... crc_tab...[]                                * 
    *                                                                   * 
    *   The algorithms use tables with precalculated  values.  This     * 
    *   speeds  up  the calculation dramaticaly. The first time the     * 
    *   CRC function is called, the table for that specific  calcu-     * 
    *   lation  is set up. The ...init variables are used to deter-     * 
    *   mine if the initialization has taken place. The  calculated     * 
    *   values are stored in the crc_tab... arrays.                     * 
    *                                                                   * 
    *   The variables are declared static. This makes them  invisi-     * 
    *   ble for other modules of the program.                           * 
    *                                                                   * 
    \*******************************************************************/ 
 
static int              crc_tab16_init          = FALSE; 
static int              crc_tab32_init          = FALSE; 
static int              crc_tabccitt_init       = FALSE; 
static int              crc_tabdnp_init         = FALSE; 
 
static unsigned short   crc_tab16[256]; 
static unsigned long    crc_tab32[256]; 
static unsigned short   crc_tabccitt[256]; 
static unsigned short   crc_tabdnp[256]; 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   static void init_crc...tab();                                   * 
    *                                                                   * 
    *   Three local functions are used  to  initialize  the  tables     * 
    *   with values for the algorithm.                                  * 
    *                                                                   * 
    \*******************************************************************/ 
 
static void             init_crc16_tab( void ); 
static void             init_crc32_tab( void ); 
static void             init_crcccitt_tab( void ); 
static void             init_crcdnp_tab( void ); 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   unsigned short update_crc_ccitt( unsigned long crc, char c );   * 
    *                                                                   * 
    *   The function update_crc_ccitt calculates  a  new  CRC-CCITT     * 
    *   value  based  on the previous value of the CRC and the next     * 
    *   byte of the data to be checked.                                 * 
    *                                                                   * 
    \*******************************************************************/ 
 
unsigned short update_crc_ccitt( unsigned short crc, char c ) { 
 
    unsigned short tmp, short_c; 
 
    short_c  = 0x00ff & (unsigned short) c; 
 
    if ( ! crc_tabccitt_init ) init_crcccitt_tab(); 
 
    tmp = (crc >> 8) ^ short_c; 
    crc = (crc << 8) ^ crc_tabccitt[tmp]; 
 
    return crc; 
 
}  /* update_crc_ccitt */ 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   unsigned short update_crc_sick(                                 * 
    *             unsigned long crc, char c, char prev_byte );          * 
    *                                                                   * 
    *   The function  update_crc_sick  calculates  a  new  CRC-SICK     * 
    *   value  based  on the previous value of the CRC and the next     * 
    *   byte of the data to be checked.                                 * 
    *                                                                   * 
    \*******************************************************************/ 
 
unsigned short update_crc_sick( unsigned short crc, char c, char prev_byte ) { 
 
    unsigned short short_c, short_p; 
 
    short_c  =   0x00ff & (unsigned short) c; 
    short_p  = ( 0x00ff & (unsigned short) prev_byte ) << 8; 
 
    if ( crc & 0x8000 ) crc = ( crc << 1 ) ^ P_SICK; 
    else                crc =   crc << 1; 
 
    crc &= 0xffff; 
    crc ^= ( short_c | short_p ); 
 
    return crc; 
 
}  /* update_crc_sick */ 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   unsigned short update_crc_16( unsigned long crc, char c );      * 
    *                                                                   * 
    *   The function update_crc_16 calculates a  new  CRC-16  value     * 
    *   based  on  the  previous value of the CRC and the next byte     * 
    *   of the data to be checked.                                      * 
    *                                                                   * 
    \*******************************************************************/ 
 
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 */ 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   unsigned short update_crc_dnp( unsigned long crc, char c );     * 
    *                                                                   * 
    *   The function update_crc_dnp calculates a new CRC-DNP  value     * 
    *   based  on  the  previous value of the CRC and the next byte     * 
    *   of the data to be checked.                                      * 
    *                                                                   * 
    \*******************************************************************/ 
 
unsigned short update_crc_dnp( unsigned short crc, char c ) { 
 
    unsigned short tmp, short_c; 
 
    short_c = 0x00ff & (unsigned short) c; 
 
    if ( ! crc_tabdnp_init ) init_crcdnp_tab(); 
 
    tmp =  crc       ^ short_c; 
    crc = (crc >> 8) ^ crc_tabdnp[ tmp & 0xff ]; 
 
    return crc; 
 
}  /* update_crc_dnp */ 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   unsigned long update_crc_32( unsigned long crc, char c );       * 
    *                                                                   * 
    *   The function update_crc_32 calculates a  new  CRC-32  value     * 
    *   based  on  the  previous value of the CRC and the next byte     * 
    *   of the data to be checked.                                      * 
    *                                                                   * 
    \*******************************************************************/ 
 
unsigned long update_crc_32( unsigned long crc, char c ) { 
 
    unsigned long tmp, long_c; 
 
    long_c = 0x000000ffL & (unsigned long) c; 
 
    if ( ! crc_tab32_init ) init_crc32_tab(); 
 
    tmp = crc ^ long_c; 
    crc = (crc >> 8) ^ crc_tab32[ tmp & 0xff ]; 
 
    return crc; 
 
}  /* update_crc_32 */ 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   static void init_crc16_tab( void );                             * 
    *                                                                   * 
    *   The function init_crc16_tab() is used  to  fill  the  array     * 
    *   for calculation of the CRC-16 with values.                      * 
    *                                                                   * 
    \*******************************************************************/ 
 
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 */ 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   static void init_crcdnp_tab( void );                            * 
    *                                                                   * 
    *   The function init_crcdnp_tab() is used  to  fill  the  array    * 
    *   for calculation of the CRC-DNP with values.                     * 
    *                                                                   * 
    \*******************************************************************/ 
 
static void init_crcdnp_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_DNP; 
            else                      crc =   crc >> 1; 
 
            c = c >> 1; 
        } 
 
        crc_tabdnp[i] = crc; 
    } 
 
    crc_tabdnp_init = TRUE; 
 
}  /* init_crcdnp_tab */ 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   static void init_crc32_tab( void );                             * 
    *                                                                   * 
    *   The function init_crc32_tab() is used  to  fill  the  array     * 
    *   for calculation of the CRC-32 with values.                      * 
    *                                                                   * 
    \*******************************************************************/ 
 
static void init_crc32_tab( void ) { 
 
    int i, j; 
    unsigned long crc; 
 
    for (i=0; i<256; i++) { 
 
        crc = (unsigned long) i; 
 
        for (j=0; j<8; j++) { 
 
            if ( crc & 0x00000001L ) crc = ( crc >> 1 ) ^ P_32; 
            else                     crc =   crc >> 1; 
        } 
 
        crc_tab32[i] = crc; 
    } 
 
    crc_tab32_init = TRUE; 
 
}  /* init_crc32_tab */ 
 
 
 
    /*******************************************************************\ 
    *                                                                   * 
    *   static void init_crcccitt_tab( void );                          * 
    *                                                                   * 
    *   The function init_crcccitt_tab() is used to fill the  array     * 
    *   for calculation of the CRC-CCITT with values.                   * 
    *                                                                   * 
    \*******************************************************************/ 
 
static void init_crcccitt_tab( void ) { 
 
    int i, j; 
    unsigned short crc, c; 
 
    for (i=0; i<256; i++) { 
 
        crc = 0; 
        c   = ((unsigned short) i) << 8; 
 
        for (j=0; j<8; j++) { 
 
            if ( (crc ^ c) & 0x8000 ) crc = ( crc << 1 ) ^ P_CCITT; 
            else                      crc =   crc << 1; 
 
            c = c << 1; 
        } 
 
        crc_tabccitt[i] = crc; 
    } 
 
    crc_tabccitt_init = TRUE; 
 
}  /* init_crcccitt_tab */