calculating XOR checksum problem

Hi everybody,

I’ve got a problem calculating a checksum for a number of bytes (11, to be exact). Just as used in NMEA, I want to take the XOR of all those bytes and use that as the final byte. The function I’m using is:

int getCheckSum(char *string) {
  int i; 
  int XOR;	
  int c;
  
  for (XOR = 0, i = 0; i < strlen(string); i++) {
    c = (unsigned char)string[i];
   
   XOR ^= c;
  }
  return XOR;
}

void test(){
char Output[12];
  
   Output[1] = id;
   
   Output[2] = (lnglatitude >> 24) & 0xff;
   Output[3] = (lnglatitude >> 16) & 0xff;
   Output[4] = (lnglatitude >> 8) & 0xff;
   Output[5] = lnglatitude & 0xff;
   
   Output[6] = (lnglongitude >> 24) & 0xff;
   Output[7] = (lnglongitude >> 16) & 0xff;
   Output[8] = (lnglongitude >> 8) & 0xff;
   Output[9] = lnglongitude & 0xff;
   
   Output[10] = (intAltitude >>8) & 0xff;
   Output[11] = intAltitude & 0xff;
   
   for(int i=1;i<12;i++){
        Serial.write(Output[i]);
   }
   
   Serial.write(getCheckSum(Output));
}

It calculates a value, but it never seems to be correct. Does it matter if one of the bytes in the middle contains 0x00?
Any pointers would be greatly appreciated!

Thanks a lot!
Jens

A zero byte in a checksum doesn't matter but you are printing the checksum as a byte which isn't correct. It has to be a 2-digit hex value.
So use:

Serial.print(getCheckSum(Output),HEX);  // or use println

It would be best if you changed the getCheckSum routine to return the checksum as an unsigned char.

Pete

If you need a byte you must do the math in byte preferably …

Bit code compacting …

uint8_t getCheckSum(char *string)
{
  int XOR = 0;	
  for (int i = 0; i < strlen(string); i++) 
  {
    XOR = XOR ^ string[i];
  }
  return XOR;
}

jensvanhoof:
I’ve got a problem calculating a checksum for a number of bytes (11, to be exact). Just as used in NMEA, I want to take the XOR of all those bytes and use that as the final byte. The function I’m using is:

  for (XOR = 0, i = 0; i < strlen(string); i++) {

c = (unsigned char)string[i];
 
  XOR ^= c;
 }




It calculates a value, but it never seems to be correct. Does it matter if one of the bytes in the middle contains 0x00?

If one of the values in the middle is 0x00, then strlen will think that it is the end of the string, so any bytes after that won’t get XORed. strlen just counts bytes in the string until it gets to a 0.

If you know your strings are always 11 bytes long, try using 11 instead of strlen.

Can you give an example of (1) the string and (2) the expected checksum and (3) your calculated checksum?

I don't think an NMEA sentence should contain a null.
Can you print the HEX value of the characters?

Thanks for all the responses guys! I'll try something out and let you know!

// a clumsy way but it works…

int inArray[] = {17,1,2,1,90};     // the input numbers will be a smaller or equal number than tempArray
int tempArray[]={0,0,0,0,0,0}; // only 6 here but you can have more

void setup(){
  for(int i=0; i<(sizeof(inArray)/sizeof(int));i++){
    tempArray[i] = inArray[i];  // fill the tempArray with values
  }
 
  int XOR = tempArray[0] ^ tempArray[1] ^ tempArray[2] ^ tempArray[3] ^ tempArray[4]  ^ tempArray[5] ^ tempArray[6];
 // zeros in the array not affect the result

  Serial.begin(9600);
  Serial.println(XOR);
}

void loop(){
}

//pejo

Moderator edit: there’s a really good reason we use CODE TAGS, and you just demonstrated it. CODE TAGS added.

char buffer[10] = {
  2,4,8};
String inString = buffer;

void setup(){
  Serial.begin(9600);

  int cSum = checkSum(inString.length());
  Serial.println(cSum);
}

void loop(){
}

int checkSum(int num){
  int XOR = 0;
  for(int i=0; i<(num); i++) {
    XOR = XOR ^ inString.charAt(i);
  }
  return XOR;
}
  for(int i=0; i<(sizeof(inArray)/sizeof(int));i++){

What happens when you wise up and see that inArray doesn’t really need to be of int type?
The expression sizeof(inArray)/sizeof(inArray[0]) will tell you the number of bytes in the array, regardless of array type.