2016-09-19 1 views
1

Je suis en train de coder une calculatrice MODBUS CRC16 en C. Ce que j'ai avant est un python qui fait ça, je voulais le convertir en C. J'ai trouvé quelques codes en ligne mais ça ne me donne pas la bonne réponse .Calcul MODBUS RTU CRC16

Pour mon code python, je ce que mon CRC16.py

#!/usr/bin/env python 

def calc(data): 
     crc_table=[0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040] 

     crc_hi=0xFF 
     crc_lo=0xFF 

     for w in data: 
       index=crc_lo^ord(w) 
       crc_val=crc_table[index] 
       crc_temp=crc_val/256 
       crc_val_low=crc_val-(crc_temp*256) 
       crc_lo=crc_val_low^crc_hi 
       crc_hi=crc_temp 

     crc=crc_hi*256 +crc_lo 
     return crc 

Ensuite, je vais utiliser un script pour entrer mes variables:

import math 
import subprocess 
import serial 
import time 
from time import sleep 
import struct 
import CRC16 
import sys 

address = chr(0x01) 
function_code = chr(0x04) 
start_at_reg = chr(0x10) + chr(0x06) 
num_of_reg = chr(0x00) + chr(0x02) 



read_device = address + function_code + start_at_reg + num_of_reg 
crc = CRC16.calc(read_device) 
crc_hi = crc/256 
crc_lo = crc & 0xFF 
print "meter add: " +str(ord(address)) 
print "crc_lo: " +str(hex(crc_lo)) 
print "crc_hi: " +str(hex(crc_hi)) 

Cela me donnera:

>> 
meter add: 1 
crc_lo: 0x95 
crc_hi: 0xa 

maintenant, j'ai trouvé ce code C en ligne pour calculer CRC16:

J'ai enregistré ce code en tant que fichier d'en-tête, "CRC.h"
WORD CRC16 (const BYTE *nData, WORD wLength) 
{ 
static const WORD wCRCTable[] = {0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040}; 

BYTE nTemp; 
WORD wCRCWord = 0xFFFF; 

    while (wLength--) 
    { 
     nTemp = *nData++^wCRCWord; 
     wCRCWord >>= 8; 
     wCRCWord ^= wCRCTable[nTemp]; 
    } 
    return wCRCWord; 

} 

Je peux donc entrer les données que j'ai:

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <errno.h> 
#include <termios.h> 
#include <stdint.h> 
#include <inttypes.h> 
#include <stdlib.h> 
#ifdef WIN32 
/*windows stuff*/ 
#else 
    typedef unsigned long WORD; 
    typedef unsigned char BYTE; 
#endif 
#include "CRC.h" 

int main(){ 
    char query_m[6]; 
    char add = 0x01; 
    char fnc_code = 0x04; 
    char reg_hi = 0x10; 
    char reg_lo = 0x06; 
    char num_hi = 0x00; 
    char num_lo = 0x02; 
    query_m[0] = add; 
    query_m[1] = fnc_code; 
    query_m[2] = reg_hi; 
    query_m[3] = reg_lo; 
    query_m[4] = num_hi; 
    query_m [5] = num_lo; 
    int i; 
    for(i=0;i<7; i++){ 
     printf("this is query_m[%d]: %d\n", i, query_m[i]); 

    } 
    int size_m = 7; 
    char crc_data; 

    crc_data = CRC16(query_m, sizeof(query_m)); 
    printf("this is CRC: %d\n", crc_data); 
    return 0; 
} 

Cela me donne une valeur de -107. Je suis relativement nouveau à C, et je fais encore quelques expériences à ce sujet

Merci.

+0

Allumez les avertissements du compilateur aussi. Vous avez déclaré 'crc_data' comme type' char', mais la fonction 'CRC16' renvoie un' WORD'. Actuellement, votre résultat sera tronqué. En outre, ne pas boucler de 0 à 6. C'est un comportement indéfini pour imprimer la valeur de 'query_m [6]'. – paddy

Répondre

1
  • WORD devrait être unsigned short (2 octets), et non unsigned long (4 ou 8 octets dépendait de la plate-forme)

    typedef unsigned short WORD; 
    
  • Comme @paddy ladite boucle de 0 à 6 dans la boucle:

    for (i=0; i<6; i++) { 
        ... 
    } 
    
  • crc_data doit être de type WORD, non char

    WORD crc_data; 
    
  • utilisation %04x dans la dernière printf()

    printf("this is CRC: %04x\n", crc_data); 
    
+0

Merci! CA aide! –