Configuring CopyStrIntoArray FB in TIA Portal for S7-1200/1500

David Krause10 min read
SiemensTIA PortalTutorial / 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

Configuring CopyStrIntoArray FB in TIA Portal for S7-1200 and S7-1500

This reference documents the correct deployment of the CopyStrIntoArray function block (FB) inside TIA Portal V15.1 through V18, targeting S7-1200 (firmware V4.2 and higher) and S7-1500 (firmware V1.8 and higher) controllers. The block copies the character payload of a STRING tag into a typed ARRAY buffer and is typically used when downstream code (peer-to-peer telegrams, ASCII protocol stacks, code-page conversion, label printing) needs character-by-character index access rather than the opaque STRING container the Siemens runtime normally provides.

The single most common deployment failure is a data-type mismatch on the FieldRead / FieldWrite instruction pair inside the block. The block body operates on CHAR elements, but users routinely wire Byte arrays. The PLC compiles fine, the call returns no error code, and the buffer fills with garbage. The procedures below eliminate that failure mode and cover the surrounding pitfalls (length handling, padding, non-printable characters, multi-byte code pages).

1. Function Block Interface and Semantics

The published CopyStrIntoArray FB exposes the following formal interface. Pin names vary by library version; the table below maps the standard convention used in the community FB circulating as CopyStrIntoArray in the Siemens global library exchange.

I/O Name Type Description
Input enable BOOL Rising edge triggers one copy operation. Level-triggered usage is permitted but causes continuous re-execution on every OB1 scan.
Input sourceString STRING[254] Source string. Max 254 payload bytes plus the implicit 2-byte length header.
Input startIndex INT Zero-based position inside sourceString where copying begins. Default 0.
Input endIndex INT Zero-based last index (inclusive) to copy. The block copies endIndex - startIndex + 1 elements.
Output done BOOL Set for one OB1 cycle when the copy completes without bounds error.
Output error BOOL Latched error flag. Reset on next rising edge of enable.
Output status WORD Diagnostic word. See error code table below.
InOut targetArray ARRAY[*] of CHAR Destination buffer. Variably sized using the * syntax (TIA V14+).
Critical: The destination must be declared as ARRAY[..] OF CHAR, not ARRAY[..] OF BYTE. The block performs implicit character conversion only when the formal parameter is CHAR. A BYTE array will compile, accept the wiring, but produce a compiler warning (Type mismatch in FB call suppressed by some users) and return indeterminate content.

2. Prerequisites

  1. Installed TIA Portal V15.1 or later. Earlier versions (V13, V14) lack the ARRAY[*] variable-length formal parameter introduced in V14 SP1.
  2. CPU firmware compatible with the formal parameter type used:
  3. Global library containing the CopyStrIntoArray FB. Obtain the .zip from your internal library server or Siemens Application Examples catalog. Verify the SHA-256 checksum before import.
  4. An instance DB for the FB call. TIA Portal generates this automatically when the FB is dragged onto a network.
  5. A STRING tag populated from an upstream process (HMI tag, receive buffer, recipe DB).
  6. A target ARRAY declared in a global DB or as a static tag of the calling FB.

3. Library Import and Master Copy Setup

  1. Open TIA Portal and load the project. In the Project tree, right-click the CPU and choose Open the global library.
  2. Select Libraries → Open global library → Browse and navigate to the supplied .zip file.
  3. Drag the CopyStrIntoArray folder from the library pane into the Program blocks node of the CPU. TIA Portal creates a Master Copy of the FB.
  4. Compile the Program blocks folder. The Master Copy is now stored in the project. Updates to the source library require manual propagation.
Field note: Many users skip the Master Copy step and drop the library copy directly into a network. The block will run, but version tracking is lost. Always create the Master Copy in Program blocks first, then drag instances from there.

4. Step-by-Step Configuration of the Call

4.1 Declare the Target ARRAY

Create a global DB (for example Data_Dest) and add a tag named CharBuffer:

CharBuffer : ARRAY[0..53] OF CHAR; // 54-character destination buffer

The dimension 0..53 matches the original example discussed in the field (54 characters). If you use a different size, update the endIndex accordingly.

4.2 Declare the Source STRING

In the same DB (or in the calling FB's Input section) add:

SourceStr : STRING[80];

Length is the maximum payload plus 1 (the trailing null is implicit). STRING[80] holds up to 80 characters.

4.3 Wire the Call

  1. Open the OB or FB where the copy should occur (typically OB1 for testing, a cyclic interrupt OB for production).
  2. From Program blocks → Master Copies, drag CopyStrIntoArray onto a network. TIA Portal creates an instance DB named CopyStrIntoArray_DB.
  3. Connect the inputs and outputs:
    • enable → tag or boolean condition (for example, "Trigger".bCopy).
    • sourceString"Data_Dest".SourceStr.
    • startIndex0 (constant INT).
    • endIndex53 (constant INT). For dynamic length, read LEN(SourceStr) - 1 from the standard function and pass it.
    • targetArray"Data_Dest".CharBuffer.
  4. Compile the block. TIA Portal performs type checking; any Byte/Char mismatch is now flagged with error 0706 "Type mismatch in the FB call".

4.4 Verify the FB Body

Open the Master Copy of the FB and inspect Network 3. The original implementation contains two instructions:

  1. %FieldRead block reading from the source STRING.
  2. %FieldWrite block writing to the destination ARRAY OF CHAR.

Both must be configured with the formal InOut parameter, not a concrete data block tag. Right-click the FieldRead input labeled Input and select Interconnect to formal parametersourceString. Repeat for OutputtargetArray.

The index inputs of the FieldRead/FieldWrite must use the same DINT tag that the block exposes internally (commonly named iIndex). Confirm by hovering the connector; the tooltip should show "#iIndex", not a global tag name.

5. Common Error Conditions

Status (hex) Meaning Likely cause Remediation
0000 OK, copy complete
8001 Enable FALSE, no operation enable tag is low Set trigger; verify logic preconditions.
8201 startIndex < 0 Negative constant passed Validate input; clamp to 0 in calling logic.
8202 endIndex > LEN(sourceString) Off-by-one or oversized constant Use LEN(sourceString) - 1 as upper bound.
8203 endIndex < startIndex Index inversion Swap indices or check upstream logic.
8204 Target array too small Array dimension smaller than copy count Resize targetArray or reduce endIndex.
8205 Type mismatch in formal parameter Target wired as BYTE array Change declaration to ARRAY OF CHAR.
8401 NULL pointer access Symbolic tag unresolved Recompile; verify that all DBs are loaded on the CPU.
Warning: The status word is application-specific. The codes above reflect the open-source variant of CopyStrIntoArray found in public libraries. If your instance uses a vendor-supplied version, consult the block's online help (Alt+F1 on the FB in TIA Portal) for the authoritative list.

6. Why BYTE Fails and CHAR Works

Siemens' STRING data type stores each character in 8 bits. The numeric representation matches BYTE (0…255), and the two are layout-compatible. The visible difference emerges at the symbolic layer:

  • CHAR is interpreted as an ASCII / ISO-8859-1 / UTF-8 code point. The TIA Portal watch table displays it as 'A'.
  • BYTE is interpreted as a numeric value. The same bit pattern appears as 16#41 or 65.

When the FB body uses FieldRead with a CHAR formal parameter, the compiler inserts a width check (DWORDCHAR = 1 byte) and emits optimized copy code. When the parameter is BYTE, the same instruction runs, but the symbolic watcher prints the cell as a number. Engineers who read the array in the watch table then see numbers instead of characters and assume the copy failed. In reality, the data is correct; the presentation layer is wrong.

If the downstream consumer requires a BYTE array (for example, a raw TCP send buffer that must be transmitted as bytes), use one of three approaches:

  1. Declare the InOut parameter as VARIANT and perform an explicit MOVE_BLK on the underlying BYTE view.
  2. Use ATC (Any Type Conversion) functions to copy CHAR to BYTE after the FB returns.
  3. Convert the destination to CHAR and re-interpret each cell as a byte when assembling the telegram. This is the recommended route for ASCII protocols.

7. Verification Procedure

After deployment, run the following checks before handing the system to commissioning:

  1. Online watch: Open the instance DB and the destination DB in a watch table. Force enable = TRUE. The done bit should pulse for one cycle and status should read 16#0000.
  2. Element comparison: In the watch table, expand the CharBuffer array. Each cell should display the corresponding character of SourceStr. If the array shows numeric values, the array was declared as BYTE. Fix the declaration and recompile.
  3. Length check: Confirm that the trailing cells (positions 54+) of the array are untouched. The FB does not clear the buffer; it only overwrites positions startIndex to endIndex. Pad the buffer with $00 or $20 before each call if your consumer is sensitive to residual content.
  4. Edge case — empty string: Set SourceStr = '' and trigger the FB. status should return 16#0000 and no array element should be modified. If status = 16#8202, the block's start index handling rejects the empty string. Wrap the call with a guard: IF LEN(SourceStr) > 0 THEN ....
  5. Edge case — extended characters: Characters above 0x7F (e.g., ü, Ö, ß in ISO-8859-1) are copied as single bytes. If the consumer expects UTF-8, encode before the call. If it expects UTF-16, do not use this FB; use Character_Set_Convert from the Siemens standard library.

8. Alternative Implementations

For projects where importing a third-party FB is undesirable, the same operation can be written in five networks of ladder or three statements of SCL:

8.1 SCL Implementation

// Copy STRING payload to ARRAY OF CHAR
// Source: SourceStr : STRING[80]
// Target: CharBuffer : ARRAY[0..79] OF CHAR

FOR #i := 0 TO MIN(LEN("Data_Dest".SourceStr) - 1, 79) DO
    "Data_Dest".CharBuffer[#i] := "Data_Dest".SourceStr[#i+1];
END_FOR;

// Pad remainder with space (0x20) or null (0x00)
FOR #i := MIN(LEN("Data_Dest".SourceStr), 80) TO 79 DO
    "Data_Dest".CharBuffer[#i] := ' ';
END_FOR;
Note: SCL uses 1-based indexing for STRING access (SourceStr[1] is the first character). When passing to a 0-based ARRAY, the loop counter must offset by 1.

8.2 Ladder / FBD Implementation

For users restricted to graphical languages, instantiate the Siemens standard block MOVE_BLK_VARIANT (S7-1500) or BLKMOV (S7-1200) and configure the source as P#DB.SourceStr BYTE 80 and the destination as P#DB.CharBuffer BYTE 80. This treats both regions as raw byte arrays and bypasses the symbolic CHAR/BYTE distinction. The price is loss of symbolic debugging; values appear as bytes in the watch table.

9. Performance and Cycle-Time Considerations

The block uses a software loop. On an S7-1516 (firmware V2.8), a 54-character copy completes in roughly 8–12 µs of OB1 time. The block is suitable for cyclic execution at 10 ms without cycle-time impact. For high-frequency burst use (1 ms OBs, 200+ bytes per call), profile with the TIA Portal Task analysis tool and consider replacing the loop with MoveBlock for a 5–10× speedup.

10. Diagnostic and Commissioning Checklist

Step Action Expected result
1 Compile project after import No warnings, no errors
2 Download program and instance DBs CPU in RUN, no SF LED
3 Force enable = TRUE with empty string status = 16#0000, buffer unchanged
4 Force SourceStr = 'Hello' and enable = TRUE CharBuffer[0..4] = 'H','e','l','l','o'
5 Force endIndex = 100 with short string status = 16#8202, error = TRUE
6 Set endIndex = 53 with 54-char string status = 16#0000, all 54 cells populated
7 Trigger 1,000 times via test OB Cycle time increase < 1 ms

11. Frequently Asked Questions

Why does my CHAR array show numeric values like 65 and 72 in the watch table?

The destination array is declared as ARRAY[..] OF BYTE instead of CHAR. TIA Portal displays BYTE cells as unsigned integers. Change the array declaration to CHAR, recompile, and reload; the watch table will then render the cells as ASCII characters.

What is the difference between FieldRead and direct array indexing in SCL?

Both produce identical runtime results. FieldRead / FieldWrite are the graphical-language equivalent of ARRAY[i] in SCL. Use whichever your project style guide mandates. FieldRead is required inside the FB body because the block cannot dereference a VARIANT parameter using array index syntax in LAD or FBD.

Can the block copy more than 254 characters?

No. The formal parameter sourceString in the published library version is typed as STRING[254], the maximum allowed by the S7-1200/1500 runtime. For longer payloads, declare a DB_ANY region and use MOVE_BLK instead.

The block does not run on my S7-1200 with firmware V4.0. Why?

Firmware V4.0 and V4.1 do not fully support the ARRAY[*] variably-sized formal parameter used in the targetArray InOut. Update the CPU to firmware V4.2 or later per the Siemens firmware update portal, or replace the ARRAY[*] formal with a fixed-size ARRAY[0..53] OF CHAR in a local copy of the FB.

How do I clear the buffer before each copy?

The block does not clear residual data. Insert a FILL_BLK call immediately before the CopyStrIntoArray call, set fill pattern to 16#00 for null padding or 16#20 for space padding, and size it to the full array length. This guarantees deterministic content for downstream code that does not handle trailing garbage.

Back to blog