S7-1200 Modbus RTU: Decoding XALIS Display 16-bit Color Registers

David Krause13 min read
S7-1200SiemensTutorial / 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

Overview

This reference documents a working Modbus RTU link between a SIMATIC S7-1200 CPU 1214C DC/DC/Rly (firmware V4.x running on TIA Portal V13/15/16) and a XALIS 9000U0 multi-line display. The non-obvious part of the integration is that the XALIS datasheet publishes logical "word" and "bit" addresses (29, 464, etc.) that engineers must remap into the Modbus 4xxxx holding-register address space before they can be entered in the DATA_ADDR input of the MB_MASTER instruction. A second pitfall is that what looks like a single Boolean variable ("red / green for line 1") is actually packed into one 16-bit holding register alongside the second line, so reading a single register gives you both colors at once as integer values 0, 1, 256, or 257.

By the end of this guide you will be able to:

  • Wire the RS485 / CM 1241 module and configure the port in TIA Portal.
  • Translate XALIS "address word" numbers into Modbus 4xxxx protocol addresses.
  • Use MB_COMM_LOAD + MB_MASTER to read and write color registers.
  • Decode the 16-bit packed word into per-line Boolean outputs.
  • Avoid common error codes (8381, 8382, 80C8) and verify the link end-to-end.

Hardware and Software Prerequisites

Item Required value Notes
S7-1200 CPU 6ES7214-1AG40-0XB0 (CPU 1214C DC/DC/Rly) or equivalent V4.x firmware Firmware >= V4.0 required for Modbus RTU master on CM 1241
Communications module 6ES7241-1CH30-1XB0 (CM 1241 RS485) or 6ES7241-1AH30-0XB0 (CM 1241 RS232) RS485 recommended for the XALIS 9000U0 half-duplex bus
Display XALIS 9000U0 (any firmware revision) Addressable as a Modbus RTU slave
Engineering tool TIA Portal V13 SP2 or newer V15 / V16 also work; the Modbus RTU library shipped with the CPU is the same
Library Siemens KB 47756141 - "How do you establish a Modbus-RTU communication with the SIMATIC S7-1200?" Contains the official MB_COMM_LOAD / MB_MASTER example project
Wiring RS485 three-wire (D+, D-, SGND) + 120 Ω termination at both ends Shielded twisted pair, shield grounded at one end only
Tip: The CM 1241 RS422/485 must be inserted in the device configuration of the S7-1200 station before you can use MB_COMM_LOAD. The block's PORT input expects the hardware identifier of the module, not the slot number.

Modbus RTU Fundamentals You Need First

Modbus RTU is a master/slave protocol over RS485 that exchanges 16-bit registers. The S7-1200 implements it as a master using two instructions from the "MODBUS (RTU)" library:

  • MB_COMM_LOAD - one-shot configuration block that loads the baud rate, parity, stop bits, flow control and block time into the chosen CM/CP port. Called once on the first PLC scan (rising edge of REQ or COLD_RESTART).
  • MB_MASTER - cyclic block that issues a single Modbus request per call. MB_MASTER must be called on a slower OB (typically OB1) and is single-instance; multiple slaves are polled by calling MB_MASTER in sequence with different DATA_ADDR values.

Every MB_MASTER transaction carries three parameters that the XALIS datasheet does not show in this form:

MB_MASTER input Meaning Typical value for XALIS 9000U0
MB_ADDR Modbus slave (unit) address 1 (set on XALIS dipswitch)
MODE Function code 0 = FC03 read holding registers, 1 = FC06 write single register, 2 = FC16 write multiple registers
DATA_ADDR Modbus protocol address of the first register (1-based for 4xxxx area) 40030 for line colors
DATA_LEN Number of 16-bit registers to read or write 2 (covers both line colors in one transaction)
DATA_PTR Pointer to a standard-access array of WORD in a DB P#DBxx.DBX0.0 WORD 4
DONE, BUSY, ERROR, STATUS Status outputs Use STATUS = 0 to confirm success

Translating XALIS "Address Word" Numbers into Modbus 4xxxx

The XALIS datasheet uses a vendor-specific notation such as "address word 29 for line-1 color" and "address bit 464 for line-1 color". These are zero-based offsets into the display's holding-register table, not the Modbus protocol address you type into DATA_ADDR. The Modbus Application Protocol Specification defines the 4xxxx reference as 1-based (so "4 0001" means the very first register, while the underlying protocol address on the wire is 0).

The translation rule is therefore:

DATA_ADDR = 40000 + (XALIS datasheet word number) + 1

For the XALIS 9000U0 color table this gives:

XALIS datasheet word # Modbus DATA_ADDR Meaning
28 40029 Reserved / status byte (line 1 green/red logical state)
29 40030 Color control word (line 1 + line 2 packed bits)
30 40031 Backlight keep-alive (0 = off, 1 = on)
464 40465 Bit alias for line-1 color inside word 29
472 40473 Bit alias for line-2 color inside word 29
Why the +1? The "4xxxx" prefix is part of the legacy Modicon reference notation and is not transmitted on the wire. Modbus protocol addresses start at 0, but the human-readable "4xxxx" reference starts at 1, so register 29 in the XALIS manual is reference 40030 and protocol address 0x001D (29 decimal). TIA Portal's DATA_ADDR accepts the human-readable 40030 form.

Why a Single Register Carries Both Line Colors

The XALIS 9000U0 encodes the color of two display lines into the LSBs of one 16-bit holding register (40030). Observed empirically:

Word written to 40030 Binary (b15..b0) Line 1 Line 2
0 0000 0000 0000 0000 Green Green
1 0000 0001 0000 0000 Green Red
256 0000 0000 0000 0001 Red Green
257 0000 0000 0000 0001 (with bit 8 set per Siemens convention) Red Red

Reading the bits in the order the Siemens support engineer confirmed:

  • Bit 0 (2^0 = 1) selects the second display line's color (1 = red).
  • Bit 8 (2^8 = 256) selects the first display line's color (1 = red).

This is why the field readings came back as 256, 257, 0, 1 rather than the 0/1 expected for a Boolean. The value "257" is simply 256 + 1: red line 1 and red line 2 set simultaneously. The two lines are not addressable as separate coils or as separate Modbus registers - they share a single holding register that you must encode and decode yourself in the PLC.

Step-by-Step: TIA Portal Configuration

1. Insert the CM 1241 in the device view

  1. Open the S7-1200 station in TIA Portal and switch to the Device view.
  2. Drag the CM 1241 RS485 (6ES7241-1CH30-1XB0) from the catalog onto the left of the CPU.
  3. Open the module's properties > Port configuration and set:
    • Baud rate: 19200 (or the value selected on the XALIS dipswitch)
    • Parity: Even (XALIS default)
    • Stop bits: 1
    • Flow control: None
    • Receive line initial state: Active
  4. Note the hardware identifier of the RS485 port (e.g. "RS485_1:0"). This is the value that goes into MB_COMM_LOAD.PORT.

2. Add the Modbus RTU library blocks

  1. Switch to the Program blocks view.
  2. Open the "Instructions" task card and navigate to Communication > MODBUS (RTU).
  3. Drag MB_COMM_LOAD (FB 1080) and MB_MASTER (FB 1081) into OB1 (or your cyclic OB).
  4. Open MB_COMM_LOAD and click "Multi-instance" or "Single instance" to generate the instance DB. Repeat for MB_MASTER.

3. Create the data DB

  1. Add a new Global DB (e.g. DB_Modbus) with standard access.
  2. Declare a 4-element WORD array named RxData for receive buffer:

RxData : ARRAY[0..3] OF WORD; // words returned by FC03 read
TxData : ARRAY[0..3] OF WORD; // words sent by FC06/FC16 write
Line1Red : BOOL; // decoded line-1 color
Line2Red : BOOL; // decoded line-2 color

4. Wire MB_COMM_LOAD (Network 1)

Call it once on the first PLC scan so the port is configured before the first MB_MASTER cycle:

// Network 1 - configure RS485 port
"MB_COMM_LOAD_DB"(REQ := "FirstScan",
                PORT := 269, // HW identifier of CM 1241 RS485
                BAUD := 19200,
                PARITY := 2, // 0=None, 1=Odd, 2=Even
                FLOW_CTRL := 0,
                RTS_ON_TOFF := 0,
                RTS_OFS_TON := 0,
                RESP_TO := 1000,
                DONE => "statCommLoadDone",
                ERROR => "statCommLoadError",
                STATUS=> "statCommLoadStatus");

5. Wire MB_MASTER for a 2-register read (Network 2)

A single FC03 read of two registers starting at 40030 returns the packed color word (register 40030) and the backlight-keep-alive word (register 40031) in one transaction. This avoids two separate polls:

// Network 2 - poll the XALIS color + backlight register every 500 ms
"MB_MASTER_DB"(REQ := "pollTrigger",
              MB_ADDR := 1, // XALIS slave address
              MODE := 0, // FC03 read holding registers
              DATA_ADDR := 40030, // color word (XALIS word 29)
              DATA_LEN := 2, // 40030 + 40031
              DATA_PTR := "DB_Modbus".RxData,
              DONE => ,
              BUSY => ,
              ERROR => "pollError",
              STATUS => "pollStatus");

6. Decode the packed color word

After every successful read, evaluate RxData[0]:

// Network 3 - decode packed color word into per-line Booleans
"DB_Modbus".Line1Red := ("DB_Modbus".RxData[0] AND 16#0100) <> 0; // bit 8
"DB_Modbus".Line2Red := ("DB_Modbus".RxData[0] AND 16#0001) <> 0; // bit 0

This is the key bit of the project: the Siemens support response states "the color information is only one bit", and the value 257 (= 0x0101) is the only confirmation needed that bit 0 selects line 2 and bit 8 selects line 1.

7. Write the color word back (Network 4)

Use FC06 (write single register) to push a new color combination. Build the integer from two Boolean inputs:

// Network 4 - compose color word and write with FC06
"DB_Modbus".TxData[0] := 0;
IF "HMI".Line1Red THEN "DB_Modbus".TxData[0] := "DB_Modbus".TxData[0] OR 16#0100; END_IF;
IF "HMI".Line2Red THEN "DB_Modbus".TxData[0] := "DB_Modbus".TxData[0] OR 16#0001; END_IF;

"MB_MASTER_DB"(REQ := "writeTrigger",
              MB_ADDR := 1,
              MODE := 1, // FC06 write single register
              DATA_ADDR := 40030,
              DATA_LEN := 1,
              DATA_PTR := "DB_Modbus".TxData,
              DONE => ,
              BUSY => ,
              ERROR => "writeError",
              STATUS => "writeStatus");

FC06 only writes one register at a time, so DATA_LEN=1 is correct here. Note that the initial attempt by the trainee used DATA_LEN=2 for the write - that wrote two registers (40030 and 40031) and overwrote the backlight keep-alive with whatever happened to be in TxData[1]. Reducing DATA_LEN to 1 is the fix when STATUS returns the error described below.

Why the Initial Attempts Returned 8381

During bring-up the FC03 request with DATA_LEN=1 at DATA_ADDR=40030 returned STATUS = 16#8381. The Modbus master error codes are documented in the S7-1200 system manual:

STATUS (hex) Meaning Likely cause on a XALIS display
8380 CRC error in the received frame Baud-rate / parity mismatch between PLC and XALIS dipswitch
8381 Slave returned an exception code (Modbus exception response) Invalid register address or read-only register, or wrong slave address on the bus
8382 Slave did not respond within RESP_TO Wrong polarity on D+/D-, missing termination, XALIS in configuration mode
80C8 Internal library error MB_COMM_LOAD not executed, or wrong PORT HW identifier

Status 8381 from DATA_ADDR=40030, DATA_LEN=1 on a XALIS is typically a "read of an unsupported range". The XALIS 9000U0 only returns the color and backlight words as a pair, so the slave rejects single-register requests against 40030 in some firmware revisions and accepts them in others. Setting DATA_LEN=2 reads both words without exception.

Reading Multiple Words and Filtering the Color Byte

The trainee's later experiment read four registers starting at 40029 (DATA_ADDR=40029, DATA_LEN=4) so the full layout of the XALIS table could be inspected. The raw response is mapped into RxData[0..3] as follows:

Index in RxData Holding register Content observed Interpretation
RxData[0] 40029 0x0000 or 0x0001 Status / line-2 color redundant copy
RxData[1] 40030 0x0000, 0x0001, 0x0100, 0x0101 Packed color word (line 2 in bit 0, line 1 in bit 8)
RxData[2] 40031 0 or 1 Backlight keep-alive
RxData[3] 40032 0xFFFF Reserved / unused

For the color application, only RxData[1] carries useful information. In production code you can either keep the 4-register read for diagnostics or switch to a 2-register read with DATA_ADDR=40030 to halve the bus traffic.

Verification Procedure

  1. Build and download the project to the S7-1200 with the CM 1241 RS485 connected to the XALIS 9000U0 (A on A, B on B, shield to PE at one end only).
  2. Go online in TIA Portal and force FirstScan=TRUE to trigger MB_COMM_LOAD. statCommLoadStatus must read 0 within 100 ms.
  3. Open the watch table on DB_Modbus. pollStatus must alternate between 0 (success) and 16#0000FFFF (no transaction pending); any non-zero value other than 0xFFFF indicates a fault - cross-reference the table above.
  4. Toggle the HMI tag HMI.Line1Red from 0 to 1. The first line of the XALIS should switch from green to red within one MB_MASTER cycle (typically < 30 ms at 19200 baud for a 4-byte payload).
  5. Set both HMI.Line1Red and HMI.Line2Red to 1. Confirm that RxData[0] reads 257 decimal (0x0101) after the next poll and that both display lines are red.
  6. Force a bus fault by unplugging the A/B wires. writeStatus must report 8382 within RESP_TO (1000 ms in the example).

Troubleshooting Matrix

Symptom Likely cause Corrective action
MB_COMM_LOAD STATUS != 0 Wrong hardware identifier on PORT Open the PLC's device configuration, click the CM 1241, copy the value from "Hardware identifier" to MB_COMM_LOAD.PORT.
MB_MASTER STATUS = 8380 Parity or baud mismatch Match CM 1241 port settings to XALIS dipswitch; check that the XALIS is in "Modbus RTU" mode (not ASCII).
MB_MASTER STATUS = 8381 Unsupported DATA_LEN for the requested address Use DATA_LEN=2 starting at 40030, or DATA_LEN=4 starting at 40029.
MB_MASTER STATUS = 8382 No reply Swap A and B; verify termination resistors (120 Ω at both ends, none in the middle); check that RESP_TO > 3.5 character times.
RxData reads 0xFFFF or 0 Wrong slave address on the bus Confirm XALIS dipswitch address matches MB_MASTER.MB_ADDR (default 1).
RxData reads 256 when both lines should be red Bit-packing mismatch with the XALIS firmware variant Read 4 words and print the raw payload; verify which bit toggles line 1.
TxData writes succeed but display ignores them Writing to a read-only address or wrong mode Confirm MODE = 1 (FC06) or 2 (FC16), DATA_ADDR = 40030, and that the XALIS is not in configuration lock.

Performance and Bus Sizing Notes

Each Modbus RTU transaction on RS485 at 19200 baud 8E1 occupies approximately 4.5 ms per frame. A 4-word FC03 read takes roughly 6 ms, a FC06 write roughly 4 ms. Polling both registers at 200 ms intervals (well above the XALIS 9000U0 50 ms minimum turnaround) leaves ample headroom on a half-duplex bus to add other slaves. Keep RESP_TO at 1000 ms unless you have a specific reason to reduce it: a too-aggressive timeout will trip 8382 errors during momentary bus contention.

The two MB_MASTER calls (read and write) cannot run simultaneously. The simplest scheduler is a "read request" pulse on a 200-ms clock generator and a "write request" pulse on an event-driven trigger such as a HMI button. Watch BUSY on the read call before issuing a write to avoid overlapping transactions.

Reference Material

Why does the XALIS datasheet show "address word 29" but MB_MASTER uses DATA_ADDR 40030?

The datasheet uses zero-based offsets; the Modbus 4xxxx reference is one-based. Add 40001 (not 40000) to the datasheet word number: 29 + 40001 = 40030. Some engineers mistakenly add only 40000 and end up at 40029, which lands on the wrong register.

What does the value 257 in the read buffer mean?

257 is decimal for 0x0101 - bit 0 set (line 2 = red) and bit 8 set (line 1 = red). The XALIS packs both line colors into one 16-bit holding register, so you must mask RxData[0] with 16#0101 to extract the two Booleans.

STATUS 8381 appears with DATA_LEN=1 on register 40030 - why?

Some XALIS 9000U0 firmware revisions reject single-register reads against the color area. Use DATA_LEN=2 starting at 40030 (or DATA_LEN=4 at 40029) so the slave replies without raising a Modbus exception. The corresponding write should still use DATA_LEN=1 with FC06 unless you want to overwrite the backlight keep-alive register 40031.

Can I use a CM 1241 RS232 instead of RS485?

Yes, electrically - the Modbus protocol itself is unchanged - but XALIS 9000U0 is hardwired for RS485 multi-drop and ships with an RS485 connector. Using RS232 forces a point-to-point topology and requires a separate RS232-to-RS485 converter on the display side. For multi-drop or longer cables (> 10 m), keep RS485 on both ends.

How fast can I poll the XALIS without errors?

At 19200 baud 8E1, the 4-word read transaction takes about 6 ms. Polling at 100 ms (10 Hz) is safe on a single-slave bus. With more slaves on the same CM 1241 port, add at least 50 ms of silence between transactions and respect the XALIS minimum turnaround time of 50 ms before issuing the next request.

Back to blog