Go Down

Topic: Getting CRC Calculation straight. (Read 2192 times) previous topic - next topic

muhkuharduino

Jun 16, 2013, 11:48 am Last Edit: Jun 16, 2013, 11:51 am by muhkuharduino Reason: 1
Code: [Select]


int pec15Table[256];
int CRC15poly = 0x4599;
char data;
int len;

void setup() {
 init_PEC15_Table(); //run once
 Serial.begin(9600); //
}

//guess this part is totally messed up
void loop() {
if (Serial.available() > 7) {
    data = Serial.read();
      len = sizeof(data);
int ergebnis = pec15(&data, len);
Serial.println(ergebnis);
  }
}

// Tabelle erstellen
void init_PEC15_Table()
{
 int remainder;
for (int i = 0; i < 256; i++)
{
remainder = i << 7;
for (int bit = 8; bit > 0; --bit)
{
if (remainder & 0x4000)
{
remainder = ((remainder << 1));
remainder = (remainder ^ CRC15poly);
}
else
{
remainder = ((remainder << 1));
}
}
pec15Table[i] = remainder&0xFFFF;
}
}

// Berechnung
unsigned int pec15 (char *data , int len)
{
int remainder,address;
remainder = 16;//PEC seed
for (int i = 0; i < len; i++)
{
address = ((remainder >> 7) ^ data[i]) & 0xff;//calculate PEC table address
remainder = (remainder << 8 ) ^ pec15Table[address];
}
return (remainder*2);//The CRC15 has a 0 in the LSB so the final value must be multiplied by 2
}


I messed it up... maybe some1 can give me useful hints
http://cds.linear.com/docs/en/datasheet/680412f.pdf page 63

Riva

You need to create a char array to store the results of serial.read and then read all your serial data (how do you know when the data has ended) into the array before calling pec15.
Another tip would be to calculate the table, print it out so you can then include it using PROGMEM as it's eating 512 bytes of valuable RAM when it does not need to.

muhkuharduino

Guess you mean something more like this:

Code: [Select]
void loop() {

if(Serial.available()>=8)
{
      for(int i=0;i<8;i++)
        {
              data[i] = Serial.read();
         }
}   
 
len = sizeof(data);
int ergebnis = pec15(data, len);
Serial.println(ergebnis);
delay(2000);
 

}

Riva


Guess you mean something more like this:

Obviously you will need to create the data array large enough to hold your maximum line length.
Your using sizeof() to determine the length of data but sizeof() will only tell you the size of the data array not the data length. You will need to maintain some sort of pointer to the next free array position that gets reset to zero after calling pec15 and this will tell you how long the data is not how long the array is.
Does the data come in fixed amounts or how do you know when the data sofar need CRC calculation doing. Is the data binary or ascii?

muhkuharduino

#4
Jun 16, 2013, 01:49 pm Last Edit: Jun 16, 2013, 01:55 pm by muhkuharduino Reason: 1
Maybe I should forget the serial.read stuff.. it was only meant for checking if the CRC formula works.

Guess there are easier options to validate this.. please have a look at the mentioned page in the link in the initial post, maybe it will clear things up a little (regarding fixed amounts of data)

e.g. on page 55 it says "SendRDCOMMcommand (0x07 0x22) and its PEC
(0x32 0xD6)"

So i could just say something like data=0x07 0x22 and then serialprintin to check if it gives me 0x32 0xD6 ?

Code: [Select]

int pec15Table[256];
int CRC15poly = 0x4599;
char data='0x070x22';
int len=8;

void setup() {
  init_PEC15_Table(); //run once
  Serial.begin(9600); //
}

void loop() {


int ergebnis = pec15(&data, len);
Serial.println(ergebnis, HEX);
delay(2000);
 

}

Riva

#5
Jun 16, 2013, 02:26 pm Last Edit: Jun 16, 2013, 02:56 pm by Riva Reason: 1
Close but your not quite there on char array. A single char can contain a value between 0 and 255. 0x07 is a way to represent the number 7 in hexadecimal and 0x22 is hexadecimal 22 (34 decimal), when the example says 0x07 0x22 that is just 2 chars not 8 as you have. Also your not letting the compiler know 'data' is an array by putting [] after the name.
Code: [Select]
int pec15Table[256];
is telling the compiler to reserve 256 int size memory locations (512 bytes as int is 2 bytes each).
Code: [Select]
char data[] = {0x7,0x22};
Does not specify the array size between [] but the data in the array is defined between the {} brackets so the compiler will still know the size the array needs to be +1

To cut a long story short here is what your looking for.
Code: [Select]
int pec15Table[256];
const int CRC15poly = 0x4599;
char data[] = {0x7,0x22};
int len;

void setup() {
 init_PEC15_Table(); //run once
 Serial.begin(9600); //
 len = sizeof(data);
 Serial.println(len);
 int ergebnis = pec15(data, len);
 Serial.println(ergebnis,HEX);
}

void loop() {
}

// Tabelle erstellen
void init_PEC15_Table() {
 int remainder;
 for (int i = 0; i < 256; i++)
 {
   remainder = i << 7;
   for (int bit = 8; bit > 0; --bit)
   {
     if (remainder & 0x4000)
     {
       remainder = ((remainder << 1));
       remainder = (remainder ^ CRC15poly);
     }
     else
     {
       remainder = ((remainder << 1));
     }
   }
   pec15Table[i] = remainder&0xFFFF;
 }
}

// Berechnung
unsigned int pec15 (char *data , int len) {
 int remainder,address;
 remainder = 16;//PEC seed
 for (int i = 0; i < len; i++)
 {
   address = ((remainder >> 7) ^ data[i]) & 0xff;//calculate PEC table address
   remainder = (remainder << 8 ) ^ pec15Table[address];
 }
 return (remainder*2);//The CRC15 has a 0 in the LSB so the final value must be multiplied by 2
}


You should really put the CRC table in flash memory to save RAM.

muhkuharduino

Thank you for you effort !

I just took a brief look into the PROGMEM story, because there are other things which should be working before ;)

I just started with this point (CRC) for no reason. I just saw the C Code example and wanted to make it run.

It now outputs "32D6". In the datasheet it says
Quote
The pec15() function calculates the PEC and will return
the correct 15 bit PEC for byte arrays of any given length.

Riva

Out of boredom I have also converted it to use PROGMEM

Code: [Select]
#include <avr/pgmspace.h>

const PROGMEM prog_int16_t pec15Table[] = {
    0,-14951,-12629,2866,-10033,7510,5732,-11267,
    -3065,12702,15020,-203,11464,-5807,-7581,10234,
    -21097,26638,25404,-22875,30040,-20287,-17421,32362,
    22928,-25591,-26821,21154,-32417,17606,20468,-30099,
    23342,-24905,-27259,20508,-31775,18040,19786,-30509,
    -20695,27312,24962,-23525,30694,-19841,-18099,31956,
    -2375,13088,14354,-629,11894,-5137,-7971,9540,
    702,-14553,-13291,2444,-9615,8168,5338,-11965,
    -3131,13916,15726,-1801,11018,-4461,-6751,8248,
    1986,-15781,-13975,3312,-8435,6804,4518,-11201,
    24146,-25653,-28423,21856,-31075,17156,18486,-29265,
    -21931,28620,25854,-24217,29338,-18685,-17359,31144,
    -22293,28018,26176,-23591,28708,-19011,-16753,31510,
    23788,-26251,-28089,22494,-31709,16826,19080,-28911,
    1404,-16155,-13353,3662,-8781,6186,4888,-10623,
    -3717,13538,16336,-1463,10676,-5075,-6369,8838,
    -24045,26506,27832,-22239,31452,-16571,-19337,29166,
    22036,-27763,-26433,23846,-28965,19266,16496,-31255,
    3972,-13795,-16081,1206,-10421,4818,6624,-9095,
    -1149,15898,13608,-3919,9036,-6443,-4633,10366,
    -1731,15524,14230,-3569,8690,-7061,-4263,10944,
    3386,-14173,-15471,1544,-10763,4204,7006,-8505,
    21674,-28365,-26111,24472,-29595,18940,17102,-30889,
    -24403,25908,28166,-21601,30818,-16901,-18743,29520,
    20950,-27569,-24707,23268,-30439,19584,18354,-32213,
    -23087,24648,27514,-20765,32030,-18297,-19531,30252,
    -959,14808,13034,-2189,9358,-7913,-5595,12220,
    2118,-12833,-14611,884,-12151,5392,7714,-9285,
    2808,-12447,-15277,458,-11721,6062,7324,-9979,
    -257,15206,12372,-2611,9776,-7255,-5989,11522,
    -22673,25334,27076,-21411,32672,-17863,-20213,29842,
    21352,-26895,-25149,22618,-29785,20030,17676,-32619
};
char data[] = {
    0x7,0x22};
int len;

void setup() {
  //init_PEC15_Table(); //run once
  Serial.begin(115200); //
  len = sizeof(data);
  Serial.println(len);
  int ergebnis = pec15(data, len);
  Serial.println(ergebnis,HEX);
}

void loop() {
}

// Berechnung
unsigned int pec15 (char *data , int len) {
    int remainder,address;
    remainder = 16;//PEC seed
    for (int i = 0; i < len; i++)
    {
        address = ((remainder >> 7) ^ data[i]) & 0xff;//calculate PEC table address
        remainder = (remainder << 8 ) ^ pgm_read_word_near(pec15Table + address);
    }
    return (remainder*2);//The CRC15 has a 0 in the LSB so the final value must be multiplied by 2
}


This will increase the compiled file size as shown in the IDE but will free 512 bytes of precious RAM.

muhkuharduino

#8
Jun 16, 2013, 03:25 pm Last Edit: Jun 16, 2013, 03:29 pm by muhkuharduino Reason: 1
:D

Page 53: Send RDCVA command (0x00 0x04) and its PEC (0x07 0xC2).

So.. if i do as following: char data[] = {0x00,0x04}; how do i check if the formula works correct?

the codesnippet returns: 7C2

I'm really confused by this hex stuff, i can only remember calculating CRC binary^^

Riva


Page 53: Send RDCVA command (0x00 0x04) and its PEC (0x07 0xC2).

So.. if i do as following: char data[] = {0x00,0x04}; how do i check if the formula works correct?

the codesnippet returns: 7C2

Your getting the correct result it's just the leading 0 of the 07 has been removed (7,C2)

Go Up