CRC 16サイクル冗長検査RTU-MODBUS標準Linux C


1、概要
CRC 16サイクル冗長検査は、メッセージの整合性を検査するためにMODBUSプロトコルでよく使用される.CRC 16検査値uint 16_t符号なし整形2バイト、MODBUSプロトコルでは、低検査バイトが前、高校検査バイトが後、例えば検査結果crc 16=0 x 1788であれば、MODBUSにおける検査順序は...0x88 0x17.
以下は自分で書いたlinux Cコードで、直接使えます.
2、Cプログラム
/*******************************************************************************
_____ ___ ____  ___   _____    _             _   _             
| ____|_ _|  _ \|_ _| |_   _|__(_)_ __   __ _| | | |_   _  __ _ 
|  _|  | || |_) || |    | |/ __| | '_ \ / _` | |_| | | | |/ _` |
| |___ | ||  _ < | |    | |\__ \ | | | | (_| |  _  | |_| | (_| |
|_____|___|_| \_\___|   |_||___/_|_| |_|\__, |_| |_|\__,_|\__,_|
  * File Name          : main.c
  * Description        : This file provides code for crc16 caculation in linuxc.
  * Author             : jackwang by [email protected]
  * Date               : 2018-07-15
*******************************************************************************/
/*! -------------------------------------------------------------------------- */
/*! Include headers */
#include 
#include 
#include 

/*! -------------------------------------------------------------------------- */
/*! Private function declarations */
static unsigned char Char2Int(char chr,bool *isOK);/*! convert char to int type*/
static unsigned char HexStr2Int(char *str, bool *isOK);/*!convert hexstr to int*/
/*! caculate crc16 of buff-input:arr_buff and length: len */
static unsigned short GenerateCRC16(unsigned char *arr_buff, unsigned short len);

/*! -------------------------------------------------------------------------- */
/*! main function defination */
int main(int argc, char* argv[])
{
  /*! variable define */
  int ret = 0;
  int numByte = argc; 
  unsigned char bccVal = 0x00;
  char inPutbuff[10];
  unsigned char databuff[1000];
  unsigned short buffsize = 0;
  unsigned short crcVal;
  bool isOK;
  int Nibb;
  
  if(argc == 1){
    printf("[note]  no params to caculate, please input hex string,
                                            splite by space!\r
"); } else{ printf("[note] input %d byte: ",numByte-1); for(int i = 1; i < numByte; i++){ printf("%s ",argv[i]); } printf("\r
"); for(int i = 1; i < numByte; i++){ memcpy(inPutbuff,argv[i],2); Nibb = HexStr2Int(inPutbuff,&isOK); if(isOK){ databuff[i-1] = Nibb; buffsize++; } } crcVal = GenerateCRC16(databuff,buffsize); printf("[note] crc16 value: 0x%04X\r
",crcVal); } return 0; } /*! -------------------------------------------------------------------------- */ /*! Private function definations */ /*! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ static unsigned char Char2Int(char chr,bool *isOK) { unsigned char nibb1; if(chr >= '0' && chr <= '9'){ nibb1 = chr - '0'; *isOK = true;} else if(chr >= 'a' && chr <= 'f'){ nibb1 = chr - 'a' + 10; *isOK = true;} else if(chr >= 'A' && chr <= 'F'){ nibb1 = chr -'A' + 10; *isOK = true; } else{ printf("[error] invalid hex str input: %c \r
",chr); *isOK = false; } return nibb1; } /*! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ static unsigned char HexStr2Int(char *str, bool *isOK) { unsigned char nibb1,nibb2; bool isOK1,isOK2; nibb1 = Char2Int(*str, &isOK1); nibb2 = Char2Int(*(str+1),&isOK2); if(isOK1 && isOK2){ *isOK = true; return nibb1*16 + nibb2; } else{ *isOK = false; return 0; } } /*! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ static unsigned short GenerateCRC16(unsigned char *arr_buff, unsigned short len) { unsigned short crc=0xFFFF; unsigned char i, j; for ( j=0; j < len;j++){ crc=crc ^*arr_buff++; for ( i=0; i<8; i++) { if( ( crc&0x0001) >0){ crc=crc>>1; crc=crc^ 0xa001; } else{ crc=crc>>1;} } } return crc; }

3、コンパイル
~$ gcc main.c -o getcrc16

4、使用
 
~$ ./getcrc16 01 03 00 04 00 04
~$ [note]  input 6 byte: 01 03 00 04 00 04
~$ [note]  crc16 value: 0xC805