When dealing with communication between two devices, often times we need to swap the bytes in the incoming/outgoing words to have the data correctly represented on both devices. Rockwell has the handy SWPB function to do this for you in ladder logic, but as far as we know Step 7 doesn’t have a block to do this for you in ladder logic. So one of our engineers took the opportunity to make a function for Siemens Step 7 that can be used to swap a chunk of words and store the swapped words in a DB of your choosing.
You might be wondering why is byteswapping necessary?
It has to do with the way the CPU stores data into its memory. You may have heard of “endianness” before. Basically there are two types of devices: Big-Endian and Little-Endian.
Big-Endian devices store the most significant portion of the word (or dword) in the first memory address.
Little-Endian devices store the least significant portion of the word in the first memory address.
So when devices that have different byte orders are talking to each other, the bytes are assembled in one order and then stored in the opposite order on the other device, causing the bytes to be reversed.
Let’s say we have a Rockwell device talking over an ANYBUS module to a Siemens device. Let’s say the Rockwell device is sending over some process data (positions of servos, analog sensor data, etc.) represented in INT form. For this example, we will assume that we have 8 INTs coming from the Rockwell device, and we need to byteswap these INTs to get the correct value stored in the Siemens device to be able to use them properly. We can use this handy byteswap block to swap the incoming words and store them in a DB all in one rung of ladder logic.
Here’s a picture of how the call to the block would look:
The unswapped ANYBUS data is stored in DB1 and the byteswapped version of the data is stored in DB2. The “dataIN” parameter is an ANY pointer that describes the chunk of words that we want to be swapped. The “dataOUT” parameter is also an ANY pointer that describes the chunk of memory we want to store the swapped words into.
So in the above example: 8 words starting at the 0th byte in DB1 will be swapped and then stored into DB2 starting at the 0th byte.
Here’s the internals of the block:
The first 2 networks are just decoding the pointers we passed in. It figures out how many words we want to swap and the DBs we are taking the info from and storing to.
Network 3 is where the magic happens. It loops through each word in the chunk of data we specified in the dataIN pointer and uses the CAW instruction
NOTE: This will only work with WORDS. If DWORDS (like reals, dints, etc.) are getting sent across, we can modify the block to use the CAD instruction to reverse the order of bytes in a double word. The code would look like this:
and the only internal code that changes in the block is network 3:
Now this block is nowhere near perfect and there are a number of different ways to accomplish byteswapping. For instance with the above method, if you declare the ANY pointer’s length in bytes, then your loop counter will be twice as long and overflow the data.
There’s a couple things you could do to prevent this from happening. As you can see in the example, we store the data type into a local variable but don’t do anything with it. We can look at the data type, if it’s not a word, int or anything that’s 2 bytes long we could either output an error maybe with an error code to let the user know there might be a mistake in the pointer they passed in, or we could just do the math to get the correct number of times to loop through the chunk of data that was passed in.