crc16校验C语言源码实例解析

发布时间 2023-06-07 10:18:27作者: 虚生

一 概念:

循环冗余码校验英文名称为Cyclical Redundancy Check,简称CRC。它是利用除法及余数的原理来作错误侦测(Error Detecting)的。实际应用时,发送装置计算出CRC值并随数据一同发送给接收装置,接收装置对收到的数据重新计算CRC并与收到的CRC相比较,若两个CRC值不同,则说明数据通讯出现错误。

二 CRC16源码解析:

1 函数实现

#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>

#define         CRC_POLY_16             0xA001
#define         CRC_START_16            0x0000

static bool             crc_tab16_init          = false;
static uint16_t         crc_tab16[256];

/*
 * uint16_t crc_16( const unsigned char *input_str, size_t num_bytes );
 *
 * The function crc_16() calculates the 16 bits CRC16 in one pass for a byte
 * string of which the beginning has been passed to the function. The number of
 * bytes to check is also a parameter. The number of the bytes in the string is
 * limited by the constant SIZE_MAX.
 */

uint16_t crc_16( const unsigned char *input_str, size_t num_bytes )
{

        uint16_t crc;
        const unsigned char *ptr;
        size_t a;

        if ( ! crc_tab16_init ) init_crc16_tab();

        crc = CRC_START_16;
        ptr = input_str;

        if ( ptr != NULL ) for (a=0; a<num_bytes; a++) {

                crc = (crc >> 8) ^ crc_tab16[ (crc ^ (uint16_t) *ptr++) & 0x00FF ];
        }

        return crc;

}  /* crc_16 */
/*
 * static void init_crc16_tab( void );
 *
 * For optimal performance uses the CRC16 routine a lookup table with values
 * that can be used directly in the XOR arithmetic in the algorithm. This
 * lookup table is calculated by the init_crc16_tab() routine, the first time
 * the CRC function is called.
 */

void init_crc16_tab( void )
{

        uint16_t i;
        uint16_t j;
        uint16_t crc;
        uint16_t c;

        for (i=0; i<256; i++) {

                crc = 0;
                c   = i;

                for (j=0; j<8; j++) {

                        if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ CRC_POLY_16;
                        else                      crc =   crc >> 1;

                        c = c >> 1;
                }

                crc_tab16[i] = crc;
        }

        crc_tab16_init = true;

}  /* init_crc16_tab */

2 计算结果:

#include <stdio.h>
#include <string.h>

typedef unsigned char uint8_t;

uint8_t test_data[20];

int main()
{
        uint16_t crc_value = 0x00;
        memset(test_data,0x11,20);

        crc_value = crc_16(test_data,10);
        printf("crc_value is:0x%x \n\r",crc_value);

        return 0;
}