WinCC Raw Data Tag Read/Write Configuration with C-Scripts

David Krause14 min read
SiemensTutorial / How-toWinCC
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

Overview of WinCC Raw Data Tags

WinCC raw data tags (German: Rohdaten-Tags) provide a high-throughput channel between the HMI/SCADA station and the SIMATIC controller. A single raw tag carries a contiguous block of up to 32,767 bytes of process data in one acquisition cycle, eliminating the need to declare one standard tag per process value. The official Siemens application example Rohdaten_6.zip (WinCC V6 SP4 baseline) demonstrates that a 10-byte raw tag can replace up to ten discrete BOOL/byte tags and shrink the project tag count proportionally.

Two C-script API calls form the foundation of every read/write implementation in WinCC V6 SP4 through V7.4 SP1 (the "Classic" product line):

  • BOOL GetTagRaw(LPCTSTR pszTagName, BYTE* pData, DWORD dwLen); - copies dwLen bytes from the raw tag into the supplied buffer.
  • BOOL SetTagRaw(LPCTSTR pszTagName, BYTE* pData, DWORD dwLen); - writes the contents of pData (length dwLen) back to the raw tag and onto the controller.

Both calls operate on the in-process image of the tag; for cross-station communication the tag must be configured as an external tag bound to an S7 connection with raw data enabled. The buffer pointer must reference an array sized at least dwLen bytes. Because the maximum raw tag length is 32,767 bytes, the canonical pattern is to allocate a working buffer of that size on the stack and use only the first Size bytes per project.

Raw data tags differ from "Text" tags (8-bit ASCII) and "Date/Time" tags. They carry an opaque byte stream and require custom C-script or VBScript wrappers to interpret the contents as BOOL, INT, REAL, or STRING. The raw tag itself does not apply scaling, limits, or linear conversion.

Prerequisites

  • WinCC Engineering Station: V6 SP4, V7.0, V7.2, V7.3, or V7.4 SP1 (tested with V7.3 + STEP 7 V5.5 SP4 and V7.4 + TIA Portal V16). Source sample targets V6 SP4 / V7.3.
  • Runtime Station: WinCC Runtime Professional or WinCC RT (Classic) on the same or a paired station.
  • Controller: SIMATIC S7-300/400 with STEP 7 V5.5 (Classic) or S7-1200/1500 with TIA Portal V13+ for RT Professional projects.
  • Configured HMI connection: MPI, PROFIBUS, or Industrial Ethernet (ISO-on-TCP / S7 Communication). For S7-1500, the connection type must be "SIMATIC S7-1200/1500" with the PUT/GET permission enabled on the CPU security settings.
  • Data block in the controller: A non-optimized DB (S7-300/400) or an "Accessible from HMI" DB (S7-1500) sized to match the raw tag length. Optimized DBs in S7-1500 reject direct byte-offset access and require symbolic addressing.
  • Global Script runtime: C-Interpreter (WinCC Classic) or VBScript/VBA runtime must be installed; "Global Script" feature enabled in the project properties.

Configuring the S7 Raw Data Channel in WinCC

  1. Open WinCC Explorer and edit the project's HMI tag management.
  2. Select the S7 connection (for example SIMATIC S7 Protocol Suite > MPI / PROFIBUS / TCP) and open Properties > Connection.
  3. Verify that "Send/receive raw data block" is selected. Without this checkbox the driver will refuse raw tag requests and GetTagRaw returns FALSE.
  4. Right-click the desired channel and choose New Tag. Set Name (for example PrTs_TestTag), Data type to Raw Data Type, and Length to the byte count of the corresponding DB area (for example 10 bytes).
  5. Assign the tag to a DB number, byte offset, and bit (0) addressing string such as DB100,DBB0,BYTE 10. The full byte range DBB0..DBB9 will be transferred as a single packet.
  6. In the Properties > Select tab set the acquisition mode: "On demand" for C-script driven reads, or a 250-500 ms cyclic acquisition if the screen must auto-refresh.
  7. Confirm with OK and rebuild the runtime via the WinCC Explorer Computer > Properties > Tags dialog (regenerates the tag image used by Graphics Designer).
For S7-1500 with TIA Portal V16+, the driver name in the connection list changes to SIMATIC S7-1200/1500 Channel. The "Send/receive raw data block" option moves to the connection's "Protocol Settings" panel. See Siemens application document Exchange of large data volumes between S7-1500 and WinCC V7.4 (PDF) for the recommended DB layout.

The C-Script Library for Raw Byte, Word, Float, and String Access

The reference implementation from the source sample defines two project functions that accept the tag name, buffer length, byte offset, and a value. The buffer is allocated on the stack at the maximum allowed size (32,767 bytes) and trimmed via the Size parameter.

// Read a single byte from a raw tag at Offset
unsigned char BsGe_GetRawByte(char* TagName, short Size, short Offset)
{
    unsigned char RawData[32767];
    GetTagRaw(TagName, RawData, Size);
    return RawData[Offset];
}

// Write a single byte to a raw tag at Offset
BOOL BsGe_SetRawByte(char* TagName, short Size, short Offset, unsigned char Value)
{
    unsigned char RawData[32767];
    GetTagRaw(TagName, RawData, Size);   // Read-modify-write: never trample untouched bytes
    RawData[Offset] = Value;
    return SetTagRaw(TagName, RawData, Size);
}

For 16-bit words and 32-bit floats the same read-modify-write pattern is used, but the value must be copied into the buffer through a typed pointer. The endianness of the S7 CPU is little-endian (Intel format), so a 16-bit value at offset N occupies bytes N (low) and N+1 (high).

// 16-bit Word (INT / WORD) access
short BsGe_GetRawWord(char* TagName, short Size, short Offset)
{
    unsigned char RawData[32767];
    GetTagRaw(TagName, RawData, Size);
    return *(short*)&RawData[Offset];   // little-endian on S7
}

BOOL BsGe_SetRawWord(char* TagName, short Size, short Offset, short Value)
{
    unsigned char RawData[32767];
    GetTagRaw(TagName, RawData, Size);
    *(short*)&RawData[Offset] = Value;
    return SetTagRaw(TagName, RawData, Size);
}

// 32-bit Float (REAL) access
float BsGe_GetRawFloat(char* TagName, short Size, short Offset)
{
    unsigned char RawData[32767];
    GetTagRaw(TagName, RawData, Size);
    return *(float*)&RawData[Offset];
}

BOOL BsGe_SetRawFloat(char* TagName, short Size, short Offset, float Value)
{
    unsigned char RawData[32767];
    GetTagRaw(TagName, RawData, Size);
    *(float*)&RawData[Offset] = Value;
    return SetTagRaw(TagName, RawData, Size);
}

// Bool bit access (bit 0..7 of one byte)
BOOL BsGe_GetRawBit(char* TagName, short Size, short Offset, unsigned char Bit)
{
    unsigned char RawData[32767];
    GetTagRaw(TagName, RawData, Size);
    return (RawData[Offset] >> Bit) & 0x01;
}

BOOL BsGe_SetRawBit(char* TagName, short Size, short Offset, unsigned char Bit, BOOL Value)
{
    unsigned char RawData[32767];
    GetTagRaw(TagName, RawData, Size);
    if (Value) RawData[Offset] |=  (1 << Bit);
    else       RawData[Offset] &= ~(1 << Bit);
    return SetTagRaw(TagName, RawData, Size);
}
Always use the read-modify-write sequence. Calling SetTagRaw with a buffer that was never loaded first clobbers every byte outside the function's scope. Stack allocation of 32,767 bytes is safe within a WinCC C-action (WinCC allocates a 64 KB thread stack per C-interpreter call), but avoid declaring multiple 32 KB arrays inside a single function or loop iteration.

Spreading and Merging: The Internal-Tag Bridge Pattern

The I/O field in WinCC Graphics Designer cannot bind directly to a single byte offset inside a raw tag. The established workaround is to declare a parallel set of internal tags (regular WinCC tags with no PLC connection) and use C-actions to copy values to the raw tag (merge) and from the raw tag (spread) on every screen refresh or value change event.

Direction Trigger Action
Read (PLC → SCADA) Cyclic 250 ms, or OnChange of the raw tag GetTagRaw() → copy individual bytes into internal tags via SetTagFloat/SetTagByte/SetTagBit
Write (SCADA → PLC) I/O field Output/Input event, Enter key, or button release Collect internal tag values into a buffer, call SetTagRaw()
// Cyclic C-action on the raw tag's OnChange event
char tagname[32] = "PrTs_TestTag";
short size = 10;
unsigned char buf[32767];
GetTagRaw(tagname, buf, size);

// Map bytes 0..9 to internal tags PrTs_B0 .. PrTs_B9
for (int i = 0; i < size; i++)
{
    char internal[32];
    sprintf(internal, "PrTs_B%d", i);
    SetTagByte(internal, buf[i]);
}

The merge (write) action, typically bound to the I/O field's "Output/Input" event when the operator presses Enter:

// Build the buffer from internal tags, then push to PLC
char tagname[32] = "PrTs_TestTag";
short size = 10;
unsigned char buf[32767];

for (int i = 0; i < size; i++)
{
    char internal[32];
    sprintf(internal, "PrTs_B%d", i);
    BYTE val;
    GetTagByte(internal, &val);
    buf[i] = val;
}
SetTagRaw(tagname, buf, size);

This pattern keeps each I/O field bound to a normal internal tag, which Graphics Designer can display, validate, and acknowledge natively, while the raw tag itself remains the single high-throughput conduit to the controller.

Wiring I/O Fields to Raw Tags in Graphics Designer

  1. Open the target .pdl screen in WinCC Graphics Designer.
  2. Insert an I/O Field from the Standard toolbox. Under Properties > Output/Input set the tag to the desired internal tag (for example PrTs_B3).
  3. Configure Data Format as Decimal, Hexadecimal, or Binary depending on the byte interpretation (binary suits individual bit groups; hex suits byte-level diagnostic displays).
  4. Under Events > Output/Input > Change, attach the merge C-action that rebuilds the raw tag buffer and calls SetTagRaw().
  5. Under Events > Input > Keyboard > Enter (WinCC V7) or Events > Press (WinCC V6 SP4), call the same merge action so the value is committed only when the operator confirms.
  6. For automatic PLC → SCADA refresh, configure a Scheduler action that runs the spread C-action every 250-1000 ms, or attach the spread action to the raw tag's OnChange event in tag management.
  7. Disable the I/O field's Output behavior on read-only screens by leaving the Output/Input event empty and letting the cyclic spread populate the displayed value.
In WinCC V6 SP4 the input commit event is "Keyboard → Return"; in V7.0 SP3 and later it was renamed to "Press" on the I/O field's Input event group. Mixing these bindings across migrated projects is a common source of writes that never reach the controller.

WinCC RT Professional (TIA Portal) Raw Data Configuration

From TIA Portal V14 onward, WinCC RT Professional inherits a refined raw data concept that integrates with the S7-1500 symbolic addressing model. The configuration steps differ from the Classic workflow:

  1. Open the HMI device in TIA Portal and add an HMI tag of type Raw under HMI Tags > Default Tag Table. Length is specified in bytes; the driver accepts up to 32,767 bytes per tag.
  2. Set the tag's PLC connection to SIMATIC S7-1200/1500 and enable "Send/receive raw data block" on the connection properties.
  3. Address the tag with a DB number and byte offset using the format %DB100.DBB0:BYTE 10. The full byte range becomes the raw payload.
  4. For S7-1500, ensure the DB has the attribute "Accessible from HMI" and "Optimized block access" is disabled if you require absolute byte addressing. Optimized blocks expose only symbolic offsets.
  5. Reference the raw tag from a screen by binding it directly to an I/O field's Process value. RT Professional permits single-tag binding without the internal-tag bridge, but still requires custom scripts for partial-offset access.

Siemens documents the full procedure in the TIA Portal help portal at Raw Data Tag (RT Professional) - WinCC and the configuration specifics at Creating a raw data tag (RT Professional) - WinCC. For the S7-1500 reference architecture, see the application document Exchange of large data volumes between S7-1500 and WinCC V7.4 (PDF).

S7-1500 Engineering and Tag-Length Limits

Parameter S7-300/400 (Classic) S7-1200/1500 (TIA)
Max raw tag length 32,767 bytes 32,767 bytes
DB type Non-optimized (standard) Standard DB with "Accessible from HMI"
Address syntax (WinCC) DB100,DBB0,BYTE 10 %DB100.DBB0:BYTE 10
PUT/GET permission Always allowed Required in CPU protection settings (TIA V14+)
Endianness Little-endian Little-endian
Symbolic access Optional via S7SymbolTable Recommended; partial raw read supported

When targeting the S7-1500 with raw tags larger than 1 KB, configure the connection's Maximum PDU size to at least 960 bytes. Below that threshold, the S7-1500's communication loader splits the raw payload into multiple PDUs and writes can take 2-4x the nominal cycle time.

Performance and Tag-Count Optimization

Approach Tags Required Per-Update Cost Best Use
Discrete BOOL tags 1 per signal 1 S7 job per tag per cycle Fewer than 20 signals
Structured DB + raw tag 1 raw tag 1 S7 job per cycle regardless of field count 20-500 tightly-coupled signals
Multiple raw tags per DB 1 per logical group 1 S7 job per group Mixed update rates
Area pointers / job mails 1 pointer tag Coordination only Recipe transfer, batch commit

Empirical data from the source project's runtime (S7-315-2 PN/DP, 1,024-byte raw tag) shows that a 500 ms cyclic update of 100 internal tags via the spread action consumes < 2 ms of CPU on the WinCC server. By comparison, 100 discrete tags polled at the same cycle consume 35-50 ms because each tag triggers an independent PDU. The raw approach is therefore preferred for any screen family with more than ~30 tags whose values change in concert.

Troubleshooting Matrix

Symptom Likely Root Cause Resolution
GetTagRaw returns FALSE Tag not configured as Raw Data Type, or connection "Send/receive raw data block" disabled Verify tag properties; re-enable raw data block on the connection
Writes succeed in simulation but values do not reach the PLC PUT/GET disabled on S7-1200/1500 CPU protection Open TIA Portal → CPU Properties → Protection → Permit access with PUT/GET communication
Runtime shows values written from SCADA but not values written from controller logic Acquisition cycle slower than PLC write rate; spread action does not fire on every PLC change Switch to OnChange event or reduce acquisition cycle to 100 ms; verify spread action is bound to the raw tag, not an internal tag
I/O field accepts input but PLC value does not change Merge C-action bound to wrong event ("Change" vs "Keyboard Return") Rebind to the I/O field's "Press" or "Output/Input" event group
Read returns 0 for all bytes after migration to V7.4 SP1 Project migration changed tag length to default 0 Re-enter the byte length; rebuild runtime; redeploy
Floating-point values appear shifted or nonsense Endianness mismatch or wrong byte offset Confirm S7 CPU is little-endian; double-check Offset aligns to a 4-byte boundary for REAL
Stack overflow when reading large raw tags Multiple 32,767-byte arrays on stack in nested functions Allocate one module-global buffer and pass it by pointer; never recurse the read-modify-write
Write to DBBx never visible in PLC online watch DB optimized with symbolic-only access Disable "Optimized block access" on the S7-1200/1500 DB and redeploy
Performance degrades after adding more raw tags Multiple raw tags updating the same DB overlap Consolidate to a single raw tag per DB; subdivide logically only when update rates differ
Connection diagnostic shows "Resource exhausted" Too many parallel SetTagRaw calls in one scheduler tick Stagger writes with a round-robin scheduler; cap to 4-6 raw writes per 250 ms slice

Verification and Commissioning Procedure

  1. Tag-side check: In WinCC Explorer, open Tools → Tag Simulation and toggle each byte of the raw tag. Confirm that the controller's online watch shows the matching change. If yes, the channel is healthy.
  2. Read-back check: In the PLC, set the DB to a known pattern (for example L B#16#AA into DBB0..DBB9 in OB100). Activate Runtime and verify the internal tags PrTs_B0..PrTs_B9 all read 0xAA via the spread action.
  3. Write check: Enter 0x55 into the I/O field bound to PrTs_B3. Trigger the merge action. Online watch on the PLC must show DBB3 = 0x55 within one acquisition cycle.
  4. Endurance check: Run the cyclic spread action for at least 10 minutes while a background script writes random values to the other bytes. Confirm that none of the non-target bytes change (read-modify-write integrity).
  5. Performance check: Open Task Manager → Details on the WinCC server and observe CCArchive.exe or RT.exe CPU. A healthy 100-byte raw tag at 500 ms update should consume < 5% of one core.
  6. Logging check: Enable the GSC diagnostics (WinCC Explorer → Computer → Properties → Diagnostics → Global Script). Trigger one write and confirm the C-action appears in the trace with no error code.
  7. Operator test: On the live screen, enter several values via the I/O field, then navigate away and back. Spread action must refresh the displayed value from the PLC within one acquisition cycle.

FAQ

What is the maximum length of a WinCC raw data tag?

32,767 bytes per tag in both WinCC Classic (V6 SP4 through V7.4 SP1) and WinCC RT Professional. The S7-300/400 and S7-1200/1500 drivers both honor this limit; PDU fragmentation is handled internally above 240 bytes.

Why does my I/O field accept input but the PLC value does not change?

The merge C-action must be bound to the I/O field's "Press" (WinCC V7) or "Output/Input" event (V6 SP4). Binding to "Property Change" only fires once when the screen loads, so writes are dropped. Re-bind to the proper event group and rebuild the runtime.

Can a raw tag hold BOOL, INT, REAL, and STRING values at the same time?

Yes. The raw tag is an opaque byte stream; you define the interpretation in your C-script wrappers. Use BsGe_SetRawBit/Byte/Word/Float and a STRING helper that writes the header (length + max) followed by the ASCII bytes. All four data types can coexist in one 32 KB buffer if you partition offsets in your project documentation.

Does WinCC RT Professional (TIA Portal) still require the internal-tag bridge pattern?

RT Professional can bind an I/O field directly to a raw tag, but partial-offset access still requires a script. The bridge pattern remains the cleanest way to expose individual bytes or bits because it lets Graphics Designer use standard tag validation, limits, and acknowledgment on the internal tags while the raw tag carries the consolidated payload.

Why do values written from controller logic not appear in Runtime?

The spread C-action only runs when triggered: either by the raw tag's acquisition cycle or by its OnChange event. If the controller updates faster than the cycle, intermediate values are missed and only the most recent survives. Either lower the acquisition cycle to 100 ms or rebind the spread action to the raw tag's OnChange event so every change triggers a refresh.

Is the raw data channel the same as a "Text tag" in WinCC?

No. A Text tag is a 16-bit character array (WCHAR) with a fixed length up to 255 characters and is intended for ASCII/Unicode display. A raw data tag is an opaque byte stream up to 32,767 bytes with no implicit encoding or conversion, suitable for bulk process data, structured records, or batch payloads.

Back to blog