Pack 4 Bytes into One Word on S7-300 and VIPA 313 RS485 Stepper

David Krause23 min read
S7-300SiemensTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Pack 4 Bytes into One Word on S7-300 and VIPA 313 RS485 Stepper

Field reference for the recurring problem of consolidating four ASCII bytes - typically the digits of a stepper address - into a single contiguous field on a Siemens S7-300 CPU or a VIPA SPEED7 313. Includes STL, LAD, and SCL examples for byte-to-word packing, RS485 ASCII frame layout, reverse unpacking, and live-drive verification.

1. Why "4 Bytes in One Word" Needs Re-Framing

A WORD on any S7-300 or VIPA SPEED7 313 is exactly 16 bits, two bytes wide. The instruction L DB10.DBW4 loads the high byte DBB4 and the low byte DBB5 as a single 16-bit value with DBB4 in the high byte (bits 8-15) and DBB5 in the low byte (bits 0-7). A DWORD or DINT is 32 bits, four bytes wide. When an engineer says "place dbb4-5-6-7 in a word so you get 1234", three operational meanings are common on a stepper RS485 link:

Practical interpretations of "4 bytes in one word"
Intent Storage used What 0x31 0x32 0x33 0x34 becomes Typical use
1. Pack 4 ASCII digits into one DWORD DBD4 (4 bytes) DBB4=0x31, DBB5=0x32, DBB6=0x33, DBB7=0x34 Passing the four digits to a function block as a single tag
2. Pack 4 ASCII digits into two adjacent words DBW4 + DBW6 (2 words) DBW4=0x3132 ("12"), DBW6=0x3334 ("34") Word-by-word transmission via PUT/GET or S7 communication
3. Convert 4 ASCII digits to one 16-bit integer DBW4 (1 word) DBW4 = 1234 dec = 0x04D2 Stepper target position register as integer

Cases 1 and 2 are physically the same data; case 3 is a numeric conversion. The choice depends on what the downstream stepper firmware expects in the RS485 ASCII frame. There is no single "correct" answer without first reading the stepper manual's frame diagram - that document drives everything else in this article.

A 16-bit WORD can never hold four separate ASCII bytes. If the application requires "one field that contains all four digits", use a DWORD (32 bits) or two adjacent WORDs (16 bits each). Trying to compress four characters into a single WORD silently truncates two of the four bytes - the most common cause of "address digits scrambled" faults on a stepper RS485 link.

2. VIPA SPEED7 313 and the Siemens S7-300 Instruction Set

The VIPA SPEED7 313 family - for example the CPU 313-5BF13 - is fully S7-300 instruction-set compatible. The data-type sizes, accumulator model, DB layout, and addressing rules are identical to those on a Siemens CPU 313C, 314, 315, 317, or 319. The CPU 313-5BF13 ships with 192 KB of work memory (typically 64 KB code, 128 KB data), 24 V DC nominal power (18-30 V range, 2 A typical draw), and a SPEED-Bus for I/O expansion. Communication options vary by sub-model; the 313-5BF13 exposes one RS485 PG/OP port and accepts an Ethernet CP343 over the SPEED-Bus for fieldbus traffic. Newer 313-6CF23 and 313-6CF33 variants add an onboard PROFINET interface and a similar 192 KB work memory partition, but the byte/word/dword model is unchanged across the family.

For RS485 ASCII toward a stepper drive, two hardware paths are typical:

  • Direct RS485 from a CP340 (1-channel, ASCII driver) or CP341 (1- or 2-channel, ASCII driver) module, configured for 7E1 or 8N1 at 9600/19200/38400 baud.
  • Onboard RS485 of the VIPA 313 (PG/OP port) repurposed with the "ASCII via SPEED-Bus" library - consult the Yaskawa / VIPA SPEED7 System Manual for the exact FB list.

All STL examples below execute unchanged on both Siemens and VIPA targets because the byte/word model, the L / T load-transfer syntax, the SLW / SLD shift instructions, and the OW / AW / XOW word logic are part of the shared instruction set. Reference the S7-300 CPU 31x Manual (Siemens support entry 12996906) for the full operation list, the S7-300 System Manual (Siemens support entry 109751400) for module-level configuration, and the Yaskawa VIPA controllers product page for SPEED7 313 hardware variants and firmware notes.

3. Byte Layout of a WORD and a DWORD

S7-300 and VIPA 313 use big-endian byte ordering for WORDs and DWORDs. A WORD loaded with L DB10.DBW4 returns DBB4 in the high byte (bits 8-15) and DBB5 in the low byte (bits 0-7). A DWORD loaded with L DB10.DBD4 returns DBB4 in the highest byte, then DBB5, DBB6, DBB7 in the lowest. The pattern is consistent across ACCU1 and ACCU2 - the 32-bit accumulators, each split into ACCU1-L (low word) and ACCU1-H (high word). Byte-level operations (for example L DB10.DBB4) implicitly zero-extend into the rest of ACCU1-L so the upper bytes do not contaminate subsequent OW operations.

S7-300 / VIPA 313 data-type widths
Tag Bytes Bit range Holds
DB10.DBB4 1 0-7 of word at DBB4 1 ASCII char
DB10.DBW4 2 0-15 2 ASCII chars ("12") or 1 unsigned INT 0-65535
DB10.DBD4 4 0-31 4 ASCII chars ("1234") or 1 DINT
DB10.DBB5 1 0-7 of word at DBB5 1 ASCII char
DB10.DBD4.%B0 (SCL) 1 lowest byte of DWORD 0x34 in the example
DB10.DBD4.%B3 (SCL) 1 highest byte of DWORD 0x31 in the example
Big-endian is the S7 standard. RS485 ASCII frames are usually little-endian in payload order (first char is byte 0). Always verify which end the stepper drive expects - the packing example in section 4 assumes the stepper reads digit 1 from the lowest-numbered byte in the PLC's view (DBB4) and digit 4 from the highest (DBB7). Flip the order with TAW on each word and a SLD 16 on the DWORD if the drive expects the opposite. Failure to verify is the most common cause of "address correct in monitor, drive still rejects" symptoms.

4. Packing 4 ASCII Bytes into a DWORD

The cleanest STL sequence for four ASCII digits already living in DBB4-DBB7:


// Already in DB10: DBB4=0x31 ('1'), DBB5=0x32 ('2'), DBB6=0x33 ('3'), DBB7=0x34 ('4')
// Load as DWORD - ACCU1 contains 0x31323334
L  DB10.DBD4
T  MD100                    // local temp DWORD
// Or store back to a single DWORD tag
L  DB10.DBD4
T  DB20.DBD50               // "1234" packed into a DWORD

If the digits must be assembled from sources other than a contiguous DB slice, use the shift-and-OR sequence on a DWORD working register. Using SLD instead of SLW is critical - SLW operates on a 16-bit word and will lose the high byte the moment the second character is OR'd in:


// Build 0x31323334 from four scalar CHAR tags
L  "addr1"                 // 0x31 in ACCU1 low byte
SLD  8                     // ACCU1: 0x00000031 -> 0x00003100
L  "addr2"                 // 0x32
OW                         // OR word: 0x00003100 | 0x00000032 = 0x00003132
SLD  8                     // 0x00003132 -> 0x00313200
L  "addr3"                 // 0x33
OW                         // 0x00313200 | 0x00000033 = 0x00313233
SLD  8                     // 0x00313233 -> 0x31323300
L  "addr4"                 // 0x34
OW                         // 0x31323300 | 0x00000034 = 0x31323334
T  "addr_packed"           // DWORD 0x31323334

The four-character view of 0x31323334 is "1234" on any ASCII terminal, including the human-readable result of a STEP 7 monitor session. Inside STEP 7, the equivalent display is "Format Display -> Character" on the VAT (Variable Table) for that DWORD. The same idea of selecting a representation that exposes the underlying bytes applies in other tools - the Microsoft Office Word field-format reference documents the \* CHARFORMAT and \* Hex switches for showing numeric or hex form of a field result, which is the same principle an engineer uses when watching a packed value in the STEP 7 VAT.

4.1 Cycle time, SFC 20 BLKMOV, and zero-extension safety

On an S7-300 CPU 313C the shift-and-OR sequence takes under 5 microseconds - the bit-instruction time of the 313C is roughly 0.1 microseconds, and the routine uses about forty primitive operations. The SFC 20 BLKMOV alternative takes a single call (~10 microseconds) and avoids the multi-step logic entirely; for a 4-byte source it is the recommended production pattern. On a VIPA SPEED7 313-5BF13 the cycle is comparable, since the SPEED7 core is rated to execute a 32-bit shift-and-OR in roughly 0.3 microseconds. For OB1 cycle-time budgets under 1 ms either approach is invisible; if the routine runs in OB35 at 100 ms it is irrelevant.

One sign-extension trap to avoid: if "addr1" is declared as INT (signed 16-bit) and contains a value above 0x7FFF, the SLD 8 will sign-extend the negative value across all 32 bits and the subsequent OW with "addr2" will corrupt the result. Two fixes are standard:


// Fix 1: load as DWORD and mask to a single byte first
L  "addr1"
L  B#16#FF
AW                          // force unsigned low byte only
SLD  8

// Fix 2: cast the source tag to BYTE in the DB declaration
// In DB10 declare "addr1" as BYTE, not as INT, so the load returns an unsigned 8-bit value

5. Packing into Two Adjacent Words (DBW4 / DBW6)

Many legacy S7-to-stepper drivers expect 16-bit word pairs. The two-word layout is also the natural output of CP340/CP341 ASCII drivers configured for "even" byte alignment, and the natural output of PUT/GET over S7 communication when the stepper gateway is a CP343-1 Lean. The packing becomes a simple aliasing operation because the bytes are already in the right places:


// Stepper reads "12" from DBW4 and "34" from DBW6
L  DB10.DBW4               // 0x3132
T  MW200
L  DB10.DBW6               // 0x3334
T  MW202
// or store directly to a target DB
L  DB10.DBW4
T  DB30.DBW20
L  DB10.DBW6
T  DB30.DBW22

If the digits arrive in scalar CHAR variables instead of a pre-aligned DB slice, the equivalent with explicit shift is:


L  "addr1"                 // 0x31
SLW  8                     // 0x3100
L  "addr2"                 // 0x32
OW                         // 0x3132 in ACCU1 low word
T  "addr_low_word"         // DBW10 = 0x3132

L  "addr3"                 // 0x33
SLW  8
L  "addr4"                 // 0x34
OW
T  "addr_high_word"        // DBW12 = 0x3334

Note that SLW 8 shifts within a 16-bit word, so the high byte is lost after the first OW. This is intentional: each of the two target WORDs holds exactly two ASCII bytes. The same sign-extension warning from section 4.1 applies if the source is declared as INT instead of BYTE.

6. Converting 4 ASCII Digits to One 16-bit Integer

If the stepper register expects the integer value 1234 (0x04D2) rather than the ASCII string "1234", the PLC must perform a base-10 conversion. STEP 7 ships a standard FC for this in the "IEC" library: FC 16 - I_STRING_TO_INT in TIA Portal, or the older FC 38 - STRING_TO_INT in STEP 7 V5.x. The simpler digit-by-digit routine is also common and avoids the STRING scaffolding:


// Inputs: DBB4..DBB7 = ASCII '1','2','3','4' (0x31..0x34)
// Output: MW100 = 1234 (0x04D2)
L  0
T  MW100                   // accumulator = 0

L  DB10.DBB4               // '1' = 0x31
L  B#16#0F                 // mask low nibble -> 0x01
AW
L  1000
*I
L  MW100
+I
T  MW100                   // MW100 = 1000

L  DB10.DBB5
L  B#16#0F
AW
L  100
*I
L  MW100
+I
T  MW100                   // MW100 = 1200

L  DB10.DBB6
L  B#16#0F
AW
L  10
*I
L  MW100
+I
T  MW100                   // MW100 = 1230

L  DB10.DBB7
L  B#16#0F
AW
L  1
*I
L  MW100
+I
T  MW100                   // MW100 = 1234

For 4-digit unsigned values the result fits in INT (-32768..32767). Negative numbers (a leading '-' character) require the IEC FC plus a sign-handling block; the digit-by-digit pattern above assumes unsigned. If the application ever needs 5 digits, a leading sign, or a value above 32767, switch to the FC and store the result in a DINT (DBD100). A common field bug: forgetting the B#16#0F mask and accidentally multiplying the full byte 0x31 (49) by 1000, producing 49000 instead of 1000. Always mask, or convert to integer first via FC 38.

7. LAD, FBD, and SCL Views

Engineers who work in LAD or FBD can implement the same packing without leaving the graphic editor. TIA Portal SCL is the recommended maintenance target for new code on S7-300 / VIPA 313 firmware >= V3.x because it compiles to identical STL on both Siemens and VIPA targets.

7.1 LAD: Packing DBW4 and DBW6 into a single DWORD

In practice LAD uses a single BLKMOV (SFC 20 "BLKMOV" or the LAD block "MOVE_BLK") instruction to copy DB10.DBD4 to MD100 or DB20.DBD50 in one rung. The block move handles all 32 bits atomically and respects the byte order without any shifting:


   --[ BLKMOV  SRCBLK := DB10.DBD4  DSTBLK := MD100 ]--
   --[ BLKMOV  SRCBLK := DB10.DBD4  DSTBLK := DB20.DBD50 ]--

7.2 FBD: Two-word shift-and-OR for scalar CHAR inputs


   SHL_WORD   WORD_OR   SHL_WORD   WORD_OR
"addr1" (SLW 8) -> "addr2" -> "addr3" (SLW 8) -> "addr4" -> DBW100

7.3 SCL (TIA Portal) equivalent

SCL makes the same logic trivially clear and is the cleanest way to express it for a 313-5BF13 or 313-6CF23 running TIA Portal V14+:


// SCL on a VIPA 313SC or S7-300 CPU 31x
// Inputs: addr1..addr4 : BYTE; output: addr_packed : DWORD
"addr_packed" := DWORD#16#00000000;
"addr_packed" := SHL_DWORD(IN := DWORD#16#00000000 OR BYTE_TO_DWORD("addr1"), N := 24);
"addr_packed" := SHL_DWORD(IN := "addr_packed" OR BYTE_TO_DWORD("addr2"), N := 16);
"addr_packed" := SHL_DWORD(IN := "addr_packed" OR BYTE_TO_DWORD("addr3"), N := 8);
"addr_packed" := "addr_packed" OR BYTE_TO_DWORD("addr4");

// Integer conversion in one line
"addr_int" := BYTE_TO_INT("addr1" AND B#16#0F) * 1000
            + BYTE_TO_INT("addr2" AND B#16#0F) * 100
            + BYTE_TO_INT("addr3" AND B#16#0F) * 10
            + BYTE_TO_INT("addr4" AND B#16#0F);

// Or use the IEC FC in TIA Portal
"addr_int" := STRING_TO_INT("addr_string");

SCL also makes the DWORD aliasing variant trivial and self-documenting. The slice syntax is supported on TIA Portal V14+ for S7-300 / VIPA SPEED7 313 firmware >= V3.x:


"addr_packed_dword" := "src_dword";        // alias copy
"addr_low_word"     := "src_dword".%W0;     // low word
"addr_high_word"    := "src_dword".%W2;     // high word
"addr_byte0"        := "src_dword".%B0;     // lowest byte
"addr_byte1"        := "src_dword".%B1;
"addr_byte2"        := "src_dword".%B2;
"addr_byte3"        := "src_dword".%B3;     // highest byte

8. Reverse Operation: Unpacking a Word to 4 Bytes

The reverse is the same logic in reverse. The follow-up question "i got a word or a integer with 4 digits, and i want the numbers separately move to 4 words" reduces to four L / T pairs on the byte addresses that live inside the word or DWORD.


// Case A: Source is a DWORD, target is 4 separate bytes
L  DB10.DBD4               // 0x31323334
T  MD100                   // 4 bytes land in MB100..MB103

L  MB100                   // highest byte = 0x31 ('1')
T  DB20.DBB100
L  MB101                   // 0x32 ('2')
T  DB20.DBB101
L  MB102                   // 0x33 ('3')
T  DB20.DBB102
L  MB103                   // lowest byte = 0x34 ('4')
T  DB20.DBB103

// Case B: Source is an integer 1234 (0x04D2), target is 4 ASCII digits
L  0
T  MD110                   // 4 ASCII result bytes

// digit 1 (thousands)
L  1234
L  1000
DIV                       // 1234 / 1000 = 1
L  48                      // ASCII '0' = 0x30
+I                        // 1 + 0x30 = 0x31 = '1'
T  MB110

// digit 2 (hundreds)  using MOD/DIV trick
L  1234
L  100
DIV                       // 1234 / 100 = 12
L  10
MOD                       // 12 mod 10 = 2
L  48
+I                        // 0x32 = '2'
T  MB111

// digit 3 (tens)
L  1234
L  10
DIV                       // 1234 / 10 = 123
L  10
MOD                       // 123 mod 10 = 3
L  48
+I                        // 0x33 = '3'
T  MB112

// digit 4 (ones)
L  1234
L  10
MOD                       // 1234 mod 10 = 4
L  48
+I                        // 0x34 = '4'
T  MB113

For DWORDs, prefer the four-byte load in Case A. For integer-to-ASCII, the FC variant is safer because it handles sign, leading zeros, and overflow without the manual digit-extraction above:


CALL  FC   37              // INT_TO_STRING
     IN   := MW300         // 1234
     RET_VAL := "addr_string"  // STRING[4] = '1234'

For the ASCII-to-integer direction, use the companion FC:


CALL  FC   38              // STRING_TO_INT (STEP 7 V5.x) or I_STRING_TO_INT (TIA)
     IN   := "addr_string" // '1234'
     RET_VAL := MW302      // 1234
Case B above extracts digits from a positive integer < 10000. For negative values the sign-extended representation makes DIV return a negative quotient, so guard the routine with a sign test and prepend the '-' character manually, or use the FC. A common field bug: forgetting the inner MOD 10 on the hundreds digit, which produces 12 (0x0C) instead of 2 (0x02) and displays as a non-printable control character on the stepper.

9. RS485 ASCII Frame Layout for a Typical Stepper

The packing decisions in sections 4-6 are driven by the drive's RS485 frame, not by the PLC's internal preferences. Three common protocols are encountered on stepper RS485 ASCII links:

9.1 Modbus ASCII frame (master -> stepper)


:  0  1  0  6  0  0  0  0  0  4  1  2  3  4  CR  LF
|  |     |        |  |  |     |  |  |  |  |     |  |
|  addr  func   refNo  wordAddr  data 4-7        |

Address and data fields are pure ASCII hex; the master pads with leading zeros. The 8 data bytes shown map directly to DBB4..DBB11 in the user's DB10 example. The trailing CR/LF is the Modbus ASCII delimiter. LRC (longitudinal redundancy check) is computed over the ASCII hex bytes excluding the colon and the CR/LF. Modbus ASCII is the most common protocol on multi-drop stepper networks; most drives default to address 1 and run at 9600/7E1.

9.2 Vendor TML frame (Technosoft / Applied Motion / Lin Engineering)


AL  '1' '2' '3' '4'  PAYLOAD...  CS  CR

Here ADDR4..ADDR1 are ASCII digits "1","2","3","4" and the stepper firmware concatenates them in that byte order. Match the packing routine in section 4 if the drive expects "1234" with DBB4='1' on the wire first. Checksum is typically the low byte of the sum of all bytes between the start delimiter and the CS field, and is computed over the on-wire byte stream - not the in-DB layout.

9.3 Vendor STP / StepperOnline ASCII frame


#  A  A  P  P  P  P  P  P  P  P  CS  CR
|  |  |  data position (signed integer, leading zero padded)
|  axis
start

Axis byte "AA" is two ASCII hex chars; position is 8 ASCII hex chars representing a 32-bit signed integer. The packing in this case is digit-by-digit ASCII in big-endian order, which matches the S7 native layout for both WORDs and DWORDs - no endian swap is required.

9.4 Common RS485 ASCII parameters

RS485 ASCII parameters and where they live in the PLC config
Parameter Typical values PLC side (DB or CP config)
Baud 9600, 19200, 38400, 115200 CP340/CP341 ASCII driver or onboard VIPA RS485
Data bits 7 or 8 DB10.DBX100.0 / DBX100.1
Parity None, Even DB10.DBX100.2
Stop bits 1, 2 DB10.DBX100.3
Flow control None, XON/XOFF DB10.DBX100.4
Termination 120 ohm on last node only External DIP on RS485 tap
Polarity A = D-, B = D+ (TIA-485-A) Verify with scope: idle line is high when A<B
Inter-character timeout 3-5 ms CP340/CP341 ASCII driver config

10. CP340 / CP341 ASCII Driver Configuration

Most S7-300 and VIPA SPEED7 313 RS485 stepper links go through a CP340 (1-channel) or CP341 (1- or 2-channel) module. The ASCII driver is the right protocol: it sends and receives raw bytes with user-defined framing, no Modbus interpretation, and no hardware handshake. Configure the CP in HW Config (STEP 7 V5.x) or in the device configuration of TIA Portal. The key parameters to set:

  • Protocol: ASCII (not 3964(R) - 3964 has its own framing layer that conflicts with Modbus ASCII's CR/LF delimiter).
  • Baud, data bits, parity, stop bits - per the stepper manual.
  • End-of-receive criteria: character-count or inter-character timeout. Stepper vendors typically use 3-5 ms inter-character timeout.
  • FIFO depth: 256 bytes (default) is fine for 8-byte stepper frames.

The standard FBs for CP340/CP341 are FB2 (P_SEND) for transmit and FB3 (P_RECV) for receive. A typical transmit call from STL in OB1:


CALL  FB   2   , DB20
     REQ  := TRUE
     LADDR := 256          // CP340 base address from HW Config
     DB_NO := 10           // source DB
     DBB_NO := 0           // start byte in DB
     LEN   := 8            // 8 bytes: 1 addr + 7 payload
     R     := FALSE
     DONE  := M100.0
     ERROR := M100.1
     STATUS := MW102

For a packed DWORD where the four ASCII digits live in DB10.DBD4, the transmit DB can be assembled at the start of OB1 with the BLKMOV from section 4, then handed to FB2 with DB_NO := 10 and DBB_NO := 0. The CP then transmits the bytes in DB order, with the most significant byte of DBD4 (DBB4 = '1') going on the wire first - matching the TML and Modbus ASCII examples in section 9. If the drive expects the opposite byte order, the BLKMOV source must be reversed - either pre-reverse the DB at packing time, or use the SCL slice syntax in section 7.3 to write the digits into DB10 in the order the drive expects on the wire.

11. Verification on a Live Drive

After loading the packing routine, run a four-step verification on the physical bus before declaring the routine correct:

  1. Send a 4-digit ASCII string from the PLC and read the wire with a portable RS485 sniffer (e.g. a USB-to-RS485 adapter running a terminal at 9600/8N1). Confirm the order is "1","2","3","4" byte-by-byte, not "4","3","2","1". A logic analyser on the A and B lines gives a definitive trace if a sniffer is unavailable.
  2. Loop back the request to the response - write a one-shot that stores the sent DWORD, issues the request, and compares the echoed payload against the original byte-by-byte.
  3. In STEP 7, open a VAT (Variable Table) and watch DB10.DBD4 in HEX display. The value must read 31323334 for the "1234" example. If the value reads 34333231, the drive expects little-endian and the packing needs an endian swap (see section 3 note).
  4. Trigger a deliberate error - send an invalid digit, e.g. DBB4 = 0xFF - and verify the drive rejects the frame with the documented error code. This confirms the validation logic on the drive side matches the framing on the PLC side.
A common field fault: the PLC monitor shows the correct packed value but the drive still rejects the address. Cause: the CRC/checksum is computed over the on-the-wire byte order, not the in-DB byte order. After any endian swap, recompute the CRC. CP340/CP341 ASCII driver can offload CRC if the protocol supports it; otherwise, do it in the PLC with FC5 (CRC_GEN on the TI-S7 block library) or with the vendor-specific FB provided by the stepper manufacturer. The S7-300 CPU 31x is rated to compute an 8-bit CRC over an 8-byte frame in under 50 microseconds, well within the inter-frame gap on any RS485 ASCII stepper link.

12. Troubleshooting Matrix and Field-Commissioning Checklist

Symptom, root cause, fix
Symptom Root cause Fix
Drive reports "address digit missing" or "invalid address" Word size mismatch - 4 bytes packed into one 16-bit WORD truncates two bytes Switch to a DWORD or two adjacent WORDs
Drive sees the digits in reverse order ("4321") Endian mismatch between PLC (big-endian) and drive (little-endian) Swap the byte order with TAW + SLW 16 sequence, or write the digits to DB in reverse
Integer conversion returns 0 ASCII mask B#16#0F applied to full bytes gives 0x01, 0x02, 0x03, 0x04 - forgot to subtract 0x30 first Use DBB - B#16#30 before the multiply, or use the FC 38 conversion
Packed value is correct in monitor but CRC fails CRC computed over wrong byte order Compute CRC over the on-the-wire byte stream after any swap
SLW 8 on a negative INT produces wrong shift Sign bit extension on signed types Use SLD (shift left double), declare the source as BYTE, or mask with 0xFF before the shift
Unpack shows the same byte 4 times Source is a WORD (2 bytes) but the routine reads 4 Match the source width - use 2-byte unpack for a WORD, 4-byte for a DWORD
RS485 driver times out on every send Termination or A/B polarity swapped Verify 120 ohm at each end; swap A and B if line stays idle-high with no traffic
CP340/CP341 reports "framing error" or "parity error" Baud, parity, or stop bits mismatch Match CP parameters to the stepper manual - 7E1 vs 8N1 is the most common difference
FC 38 STRING_TO_INT returns 0 unexpectedly Source string is not terminated or has trailing spaces Right-trim spaces and ensure the string length is correct before the call
VIPA 313 PG/OP port goes into STOP when ASCII traffic starts PG/OP port multiplexed with programming - port ownership conflict Disable programming on the PG/OP port in HW Config or move ASCII to a CP340/CP341

Field-commissioning checklist (run before first production send):

  • Confirm the drive manual lists the exact byte order for the address field - this is the single biggest source of "packed right, wire wrong" faults.
  • Pre-allocate the DB with the digit bytes in their natural DB order before any shift logic; reserve 4 bytes per address field to allow DWORD packing.
  • Set a watch on DB10.DBD4 in HEX view in the VAT, not as characters - hex view reveals endian errors immediately.
  • If using the VIPA 313 onboard RS485 (PG/OP), disable programming-port multiplexing before opening the ASCII channel; otherwise the CPU goes STOP when the port switches owner.
  • For production code, replace the digit-by-digit ASCII-to-int sequence with FC 38 / FC 16 from the IEC library - the loop is slower than a single FC call and obscures intent.
  • Always compute the checksum after the final byte order, never before.
  • For multi-drop RS485, enable termination at both physical ends only - middle nodes must be off the bus terminator. A mis-placed 120-ohm resistor attenuates the signal by half.
  • Document the packing choice (DWORD vs two WORDs vs integer) in the DB header comment so the next engineer does not have to re-derive it from the STL.
  • Capture a logic-analyser trace of the first 10 frames on a new install and file it with the commissioning report. Endian and CRC errors that pass a single-frame test often fail only on the 5th or 6th frame.

FAQ

Can a 16-bit WORD really hold 4 ASCII bytes?

No. A WORD on S7-300 and VIPA SPEED7 313 is 16 bits wide and holds exactly two bytes. To keep four ASCII digits in a single contiguous field, use a DWORD (32 bits, four bytes) or two adjacent WORDs. Trying to fit four bytes into a 16-bit WORD truncates the upper two bytes silently and is the most common cause of "address digits scrambled" faults on a stepper RS485 link.

What is the difference between SLD and SLW for packing bytes?

SLD shifts a DWORD (32 bits) left by the given number of bits; SLW shifts a WORD (16 bits). When packing four ASCII bytes into a 32-bit field, use SLD 8 between each load so the result is a DWORD. If you use SLW on a 16-bit value, the high byte is lost when the next byte is OR'd in, and the routine silently produces a 16-bit value with the last two bytes overwritten.

How do I read a single byte from the middle of a packed DWORD?

Load the DWORD into ACCU1, then use the byte-pointer form. The simplest field pattern is to copy the DWORD to a local MD (e.g. T MD100) and read MB100 through MB103 in subsequent logic. Each MB is one of the four bytes in big-endian order on S7-300 / VIPA 313. In TIA Portal SCL, the slice syntax "src_dword".%B0 through %B3 provides the same access with explicit indexing.

Is VIPA 313 program-compatible with Siemens S7-300?

Yes. The VIPA SPEED7 313 family (CPU 313-5BF13 and similar) runs the same STEP 7 instruction set as the Siemens S7-300 CPU 31x. STL examples in this article execute unchanged on both platforms. Differences are limited to hardware options, the SPEED-Bus for I/O expansion, and the engineering tools (STEP 7 V5.x or TIA Portal for newer firmware). See the S7-300 CPU 31x manual on the Siemens support site for the canonical reference.

Why does my packed value display correctly in monitor but the stepper still rejects it?

Most stepper RS485 ASCII frames specify the byte order of the address field explicitly. The S7-300 / VIPA 313 is big-endian, but many stepper protocols expect little-endian on the wire. Read the drive's frame diagram, and if the on-wire order is reversed, swap the bytes before transmitting. Recompute the CRC after the swap - the CRC is taken over the byte stream actually sent, not the in-memory layout.

Back to blog