Studio 5000 v32 creating checksum

Webhead

Member
Join Date
Jun 2005
Location
Central Florida
Posts
145
Hello all,

I'm trying to recreate the following checksum calculation in the PLC. The example is written in C++ of which I am not very familiar and I need to calculate the checksum on the fly to read and write many different values from an ASCII device. Anybody got a good direction for me to be pointed?

For transmitted commands, include all characters in the command section
in the sum. To verify received responses, include all characters up to
the checksum (but not including it) in the sum. A sample checksum calculation
implementation in the C++ programming language is: unsigned
short CalculateChecksum (const unsigned char* pData, int DataLen).
{
unsigned long CS = 0;
unsigned short* psData = (unsigned short*)pData;
for (int Index = 0; Index < (DataLen / 2); Index++, psData++)
CS += *psData;
If (DataLen % 2 != 0)
CS += pData[DataLen - 1];
CS = (CS >> 16) + (CS & 0xFFFF);
CS += (CS >> 16);
return (unsigned short) ~CS;
}
 
I've asked the vendor what type it is from the vendor and am waiting on a response.

Basically I want to take a ASCII value and convert the individual characters to hex, then take the hex values and arrange in least significant most significant byte, add the hex values together and invert the value to get the checksum. I'm just not really sure where to start....

Anybus.PNG
 
ok, that looks like a standard XOR against FFFFFFFF.

I would use the XOR instruction after you sum the hex values
 
Last edited:
Vendor just got back with me and said the checksum is based on IPv4 header checksum. I don't know if that's any help....

Having an issue trying to convert values to hex, is there a function for this?
 
Having an issue trying to convert values to hex, is there a function for this?


Funny you should ask, there is recent thread on the same topic:



https://www.plctalk.net/qanda/showthread.php?t=102743




Another way to do this is a lookup table:

  • Create HEXARRAY with 48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70
    • N.B. those are the ASCII codes for "0123456789ABCDEF" at indirect addresses 0 to 15 (0h to Fh)
  • Extract the first nibble from the checksum:
    • AND CS f0h CSnibble DIV CSnibble 16
      • Bit-wise AND with 11110000b
      • Shift right four bits via divide by 16
  • Move HEXARRAY[CSnibble] to the high hex checksum address in the message
  • Extract the second nibble from the checksum
    • AND CS 0fh CSnibble
      • Bit-wise AND with 00001111b
  • Move HEXARRAY[CSnibble] to the low hex checksum address in the message
 
Last edited:
Code:
[COLOR=blue][B]// Function returns a 16-bit unsigned integer, 
[/B][/COLOR]unsigned short

[COLOR=blue][B]// which is the same as two bytes, which bytes will have to be[/B][/COLOR]
[COLOR=blue][B]// converted to their four hexadecimal ASCII chars elsewhere.[/B][/COLOR]
[COLOR=blue][B]// N.B. beware byte order![/B][/COLOR]
[COLOR=blue][B]// - The first argument is pData[/B][/COLOR]
[COLOR=blue][B]//   - a pointer to the first of the series of characters[/B][/COLOR]
[COLOR=blue][B]//     that compose the command action[/B][/COLOR]
[COLOR=blue][B]// - The second argument is DataLen[/B][/COLOR]
[COLOR=blue][B]//   - the number of characters in the command action[/B][/COLOR]
CalculateChecksum (const unsigned char* pData, int DataLen).
{


[COLOR=Blue][B]// CS is a 32-bit unsigned integer that well keep track of[/B][/COLOR]
[COLOR=Blue][B]// the running sum, then be converted to the checksum[/B][/COLOR]
unsigned long CS = 0;


[B][COLOR=blue]// psData is a pointer to the start of the series of characters[/COLOR][/B]
[B][COLOR=blue]// in the command action,[/COLOR][/B]
[B][COLOR=blue]// but it is treated by the C++ compiler as a pointer to a[/COLOR][/B]
[B][COLOR=blue]// series of unsigned 16-bit integers.  I.e.[/COLOR][/B]
[B][COLOR=blue]// - psData points to pData series character 0[/COLOR][/B]
[B][COLOR=blue]// - psData+1 points to pData series character 2[/COLOR][/B]
[B][COLOR=blue]// - psData+n points to pData series character 2n[/COLOR][/B]
unsigned short* psData = (unsigned short*)pData;

[COLOR=Blue][B]
  // Loop over pairs of characters (bytes) in command action 
  // [/B][/COLOR][COLOR=Blue][B][COLOR=Blue][B](i.e. [/B][/COLOR][0,1], [2,3], [4,5], etc,), treat them as unsigned
  //[/B][/COLOR][COLOR=Blue][B][COLOR=Blue][B] 16-bit[/B][/COLOR] integers via psData[/B][/COLOR]
  for (int Index = 0             [B][COLOR=blue]// Start at 16-bit Index 0[/COLOR][/B]

                                [B] [COLOR=blue]// At start of each loop pass[/COLOR][/B]
       ; Index < (DataLen / 2)   [COLOR=Blue][B]// - Stop after last full pair[/B][/COLOR]

                                 [COLOR=blue][B]//   of chars[/B][/COLOR]
 
                                 [B][COLOR=blue]// At end of each loop pass[/COLOR][/B]
       ; Index++,                [B][COLOR=blue]// - Increment Index by 1[/COLOR][/B]
       , psData++)               [COLOR=blue][B]// - Increment 16-bit pointer[/B][/COLOR]
[COLOR=blue][B]                                  //   by 1, [I][COLOR=Red]which increments by[/COLOR][/I][/B][/COLOR]
[COLOR=blue][B][I][COLOR=Red]                                  //   2 in command action chars[/COLOR][/I]
[/B][/COLOR]
  {
[COLOR=Blue][B]     // In each loop pass, add next two chars to CS (checksum).[/B][/COLOR]
[COLOR=Blue][B]     // treating those two chars as a single unsigned 16-bit[/B][/COLOR]
[COLOR=Blue][B]     // integer.  N.B. there may be overflow, but CS is 32-bit[/B][/COLOR]
[COLOR=Blue][B]     // so that overflow will be in bits 16 and up[/B][/COLOR]
    CS += *psData;
  }

[COLOR=Blue][B]   // If the command action length is odd, then the last command[/B][/COLOR]
[COLOR=Blue][B]   // action character (byte) was not added to the checksum by[/B][/COLOR]
[COLOR=Blue][B]   // the loop above; add it here[/B][/COLOR]
[COLOR=Blue][B]   // - % is the modulo [/B][/COLOR][COLOR=Blue][B][COLOR=Blue][B]binary[/B][/COLOR] operator e.g. (34 % 10) => 4[/B][/COLOR]
[COLOR=Blue][B]   //   - (blah % 2) will yield 0 if blah is even, or 1 if odd[/B][/COLOR]
[COLOR=Blue][B]   //[/B][/COLOR]
[COLOR=Blue][B]   // N.B. This effectively pads any odd-length command action[/B][/COLOR]
[COLOR=Blue][B]   //      method with a single char (byte) with value 0, for[/B][/COLOR]
[COLOR=Blue][B]   //      the purpose of calculating the checksum[/B][/COLOR]
  If (DataLen % 2 != 0)
  {
    CS += pData[DataLen - 1];
  }

[B][COLOR=blue]   // Add low and high 16-bit words of 32-bit checksum,[/COLOR][/B]
[B][COLOR=blue]   // place resulting sum in checksum.[/COLOR][/B]
[B][COLOR=blue]   // - >> is right-shift binary operator; in this case it[/COLOR][/B]
[B][COLOR=blue]   //   is equivalent either to dividing by 65536 (10000f)[/COLOR][/B][B][COLOR=blue],[/COLOR][/B]
[B][COLOR=blue]   //   or to sixteen BSRs,[/COLOR][/B]
[B][COLOR=blue]   // - & is bit-wise AND binary operator; 0xFFFF is FFFFh[/COLOR][/B]
[B][COLOR=blue]   // N.B. I have never seen a checksum that used the carry[/COLOR][/B]
[B][COLOR=blue]   //      i.e. the high 16-bits of the 32-bit sum of 16-bit,[/COLOR][/B]
[B][COLOR=blue]   //      but here it is[/COLOR][/B]
  CS = (CS >> 16) + (CS & 0xFFFF);

[B][COLOR=blue]   // Add the high bits again, in case the previous sum resulted[/COLOR][/B]
[B][COLOR=blue]   // in a carry beyond the low 16-bits[/COLOR][/B]
  CS += (CS >> 16);

[COLOR=blue][B]   // Invert the bits of the checksum,[/B][/COLOR]
[COLOR=blue][B]   // cast (convert) to an unsigned 16-bit integer (drop hi 16),[/B][/COLOR]
[COLOR=blue][B]   // and return the unsigned 16-bit checksum  [/B][/COLOR]
  return (unsigned short) ~CS;
 }
 
Thank you all for your help but as it turns out I was not given all the details and the checksum that was needed to be calculated in the PLC is not needed now.
 

Similar Topics

I'm adding an IAI Gateway with 2 axes connected to it. To an ethernet network on my PLC. So, I think the math is correct on the Input and Output...
Replies
0
Views
147
Got a repaired laptop back from warranty and loaded it up with all my software, unfortunately with my version V32.03 Studio 5000 I cannot change...
Replies
3
Views
193
Hi, I am having issues with Studio 5000 v32.02 and connecting to a 523 PowerFlex drive via Ethernet. My network consists of a 5380 CompactLogix...
Replies
11
Views
1,779
installed v32 on server 2016 and when i open studio 5000 it freezes on the logo screen any ideas to why
Replies
2
Views
1,682
I am a big fan of developing in Logix Emulate when I don't have access to a live PLC. That said I am running into an issue with not being able to...
Replies
1
Views
1,539
Back
Top Bottom