S7-1200 ASCII Serial Communication with CM 1241 RS485: Complete Engineering Guide
Interfacing an S7-1200 PLC to a third-party temperature controller that exposes only a raw RS485 ASCII protocol (no Modbus, no USS) is one of the most common—and most error-prone—commissioning tasks in compact PLC projects. The SIMATIC S7-1200 family supports this scenario natively through the CM 1241 communication modules and the Point-to-Point (PtP) instruction set built into the S7-1200 CPU firmware. This guide walks through the full engineering cycle: module selection, wiring, TIA Portal hardware configuration, ASCII frame construction, SEND_PTP/RCV_PTP programming, receive buffer parsing, and field verification.
1. CM 1241 Communication Module Selection
The S7-1200 CPU does not have a native serial port; ASCII traffic must pass through an add-on communication module or communication board. The available variants differ in electrical interface, supported protocols, and physical form factor.
| Module | MLFB / Catalog No. | Interface | Max Baud | Termination | Form Factor |
|---|---|---|---|---|---|
| CM 1241 RS232 | 6ES7241-1AH32-0XB0 | RS-232C, 9-pin D-sub | 115.2 kbit/s | N/A | Signal Board (left side) |
| CM 1241 RS422/485 | 6ES7241-1CH32-0XB0 | RS-422/RS-485, 2-wire or 4-wire | 115.2 kbit/s | Internal DIP switch | Signal Board (left side) |
| CB 1241 RS485 | 6ES7241-1CH30-1XB0 | RS-485, 2-wire only | 115.2 kbit/s | Internal DIP switch | Communication Board (under terminal cover) |
For a single temperature controller on a 2-wire RS-485 multidrop bus, the CB 1241 RS485 (6ES7241-1CH30-1XB0) is the lowest-cost solution and is electrically isolated. The CM 1241 RS422/485 (6ES7241-1CH32-0XB0) adds a full RS-422 mode and is preferred when the device supports 4-wire full-duplex ASCII. Both modules support the ASCII point-to-point protocol directly from the CPU firmware; no additional FBs are required.
For full module specifications, refer to the S7-1200 Programmable Controller System Manual.
2. RS-485 Bus Wiring and Termination
RS-485 is a balanced, differential bus. A single shielded twisted pair carries the data, and a third conductor (or the shield) provides the signal common. Correct termination is critical for reliable ASCII communications above 19200 bit/s or on cable runs longer than ~10 m.
-
Enable internal termination on the CM/CB 1241 by moving the DIP switch labeled
TERMto theONposition. The module installs a 120 Ω resistor between the A and B lines. - Match the controller's biasing. If the temperature controller does not provide failsafe bias, externally bias the bus with a 620 Ω pull-up to +5 V on line B and a 620 Ω pull-down to GND on line A.
- Use a shielded twisted pair with characteristic impedance of 120 Ω (e.g., Belden 3106A or Alpha 6412). Ground the shield at one end only (typically the PLC cabinet).
-
Verify polarity. Siemens labels the positive line as
T/R+(also A) and the negative asT/R-(also B). Some controller vendors reverse the labels — always check against the device's datasheet, not its marketing pinout. - Maximum cable length at 115.2 kbit/s is 1000 m (3280 ft). At 19.2 kbit/s it is 1200 m. Total stub length must be < 1/10 of the trunk length to prevent reflections.
3. ASCII Protocol Fundamentals
Unlike Modbus RTU, ASCII (American Standard Code for Information Interchange) is a character-oriented protocol. Each byte in the frame is sent as a 7- or 8-bit ASCII code, prefixed by a start bit and terminated by a stop bit. Frames are bounded by delimiter characters, which makes the protocol tolerant of inter-character gaps but inefficient on the wire (~50% overhead vs. RTU).
| Byte Index | Field | Example (hex) | Description |
|---|---|---|---|
| 0 | Start delimiter |
3A (':') |
Every command/response begins with this character |
| 1 | Address (MSB) | 30 |
ASCII '0' = device address 0 |
| 2 | Address (LSB) | 31 |
ASCII '1' = device address 1 |
| 3 | Command | 52 |
ASCII 'R' = Read Process Value |
| 4..n-3 | Data |
31 32 33 2E 35 ('123.5') |
ASCII numeric payload |
| n-2 | Checksum (high nibble) | 34 |
ASCII '4' |
| n-1 | Checksum (low nibble) |
35 (CR) |
ASCII '5' |
| n | End delimiter | 0D 0A |
CR LF pair |
The checksum is typically a 2's-complement sum of all bytes between the start and checksum, expressed as a single ASCII hex byte. Always refer to the controller's manual; some vendors use XOR, some use CRC-8, and a few (incorrectly) use Modbus LRC.
4. Hardware Configuration in TIA Portal
Open TIA Portal, expand Devices & Networks, and add the CPU. The CM/CB 1241 is auto-detected when plugged in (online) or added manually (offline). Configure the module's port as follows:
- In the Device View, click the CM 1241 module icon.
- Open the Properties > Port Configuration tab.
- Set the following parameters for a typical temperature controller:
| Parameter | Value | Notes |
|---|---|---|
| Protocol | ASCII | Free-port (PtP) mode |
| Baud rate | 9600 / 19200 / 38400 | Match the controller; 9600 is the safe default |
| Parity | None / Even | Most ASCII controllers use None-8-1 |
| Data bits | 8 | ASCII protocol always uses 8 data bits |
| Stop bits | 1 | 2 if the controller specifies even parity with 8 data bits |
| Flow control | None | RS-485 is half-duplex; XON/XOFF is supported but rarely used |
| End of receive | After character timeout (4 ms) | Use the timeout method for variable-length ASCII frames |
| Character timeout | 4 ms (or 3.5 char times) | Defines inter-frame gap detection |
For a full module manual including the protocol field reference, see the S7-1200 Programmable Controller System Manual, chapter 7 "Communication processor and Modbus TCP".
269. This ID is required by every PtP instruction and must be passed through a tag or constant. You can read the HW-ID in the device properties under System constants.
5. SEND_PTP and RCV_PTP Instruction Set
The PtP instruction library lives in the TIA Portal Instructions > Communication > Communication processor > Point-to-Point task card. For S7-1200 firmware V4.0 and later, the relevant FBs are:
| Instruction | FB Number | Purpose | Polling Mode |
|---|---|---|---|
| SEND_PTP | FB 3 | Transmit a buffer via the configured CM 1241 port | REQ edge-triggered |
| RCV_PTP | FB 2 | Receive bytes into a buffer; triggered by idle-line or character timeout | EN = TRUE continuous |
| RCVREC | — | Reset the receive buffer (alternative to RCV_PTP EN reset) | Conditional call |
| PTP_CFG | — | Reconfigure the port at runtime (optional) | One-shot on startup |
| PTP_RST | — | Reset the physical port and clear all internal state | One-shot on fault |
The RCV_PTP instruction does not work like a normal polled call. According to the S7-1200 system manual, the FB must be called continuously in a cyclic OB (typically OB1). Internally, RCV_PTP looks for the configured end-of-receive condition (idle line, character timeout, or message count). When that condition is met, the instruction copies the accumulated bytes into the user buffer and sets DONE for one cycle. The next call with a rising edge on ENR (the internal enable receive input) restarts the buffer.
6. Structured Text Implementation
The following example shows a complete polling loop in SCL (Structured Control Language). The PLC requests the process value from device address 01, then parses the ASCII response into a floating-point temperature.
6.1 Data Block Definition
DATA_BLOCK "dbPtPComm"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
NON_RETAIN
STRUCT
bSendReq : Bool; // Edge-trigger to send next request
bTxBusy : Bool; // SEND_PTP.BUSY mirror
bTxDone : Bool; // SEND_PTP.DONE mirror
bTxError : Bool; // SEND_PTP.ERROR mirror
wTxStatus : Word; // SEND_PTP.STATUS
bRxBusy : Bool; // RCV_PTP.BUSY mirror
bRxDone : Bool; // RCV_PTP.DONE mirror
bRxError : Bool; // RCV_PTP.ERROR mirror
wRxStatus : Word; // RCV_PTP.STATUS
rTemperature : Real; // Parsed process value in degC
bParseOK : Bool; // TRUE if checksum + format valid
END_STRUCT;
END_DATA_BLOCK
6.2 Send Request (Polling Logic)
"dbPtPComm".bSendReq := NOT "dbPtPComm".bTxBusy AND NOT "dbPtPComm".bRxBusy;
The bSendReq flag is asserted whenever both the transmit and receive paths are idle. It triggers a new request and falls as soon as SEND_PTP accepts the buffer.
6.3 SEND_PTP Call (OB1)
// Build the ASCII request frame: ':01R' + Checksum + CRLF
// For a controller that uses 2's-complement sum modulo 256:
// 0x3A + 0x30 + 0x31 + 0x52 = 0xF7, 2's-comp = 0x09 -> ASCII '0' '9'
// Transmit buffer = 16#3A 16#30 16#31 16#52 16#30 16#39 16#0D 16#0A
"iSendPTP"(REQ := "dbPtPComm".bSendReq,
LADDR := 269, // HW identifier of CM 1241 port
SEND := P#DB100.DBX0.0 BYTE 8, // Points to the static frame buffer
DONE => "dbPtPComm".bTxDone,
ERROR => "dbPtPComm".bTxError,
STATUS=> "dbPtPComm".wTxStatus,
BUSY => "dbPtPComm".bTxBusy);
The iSendPTP instance DB is created automatically when the FB is dropped into the program. The SEND parameter is a pointer to the 8-byte transmit buffer in a separate data block (here DB100) that you pre-load once with the frame, including the calculated checksum.
6.4 RCV_PTP Call (OB1, called every cycle)
"iRcvPTP"(EN_R := TRUE, // Continuous receive enable
LADDR := 269,
DATA := P#DB101.DBX0.0 BYTE 64, // 64-byte receive buffer
LEN := "iRcvPTP".LEN, // Actual bytes received
DONE => "dbPtPComm".bRxDone,
ERROR => "dbPtPComm".bRxError,
STATUS=> "dbPtPComm".wRxStatus,
BUSY => "dbPtPComm".bRxBusy);
// Reset the receiver after a successful or failed read
IF "dbPtPComm".bRxDone OR "dbPtPComm".bRxError THEN
"iRcvPTP".EN_R := FALSE; // Pulse OFF for one cycle
// ... and re-arm in the next cycle
END_IF;
DB101 is a 64-byte buffer that the FB fills in with received bytes. After every successful DONE pulse, the buffer length is read out of iRcvPTP.LEN for the parser.
7. Parsing the ASCII Response into a REAL
Most temperature controllers return the value as a decimal ASCII string. The parser must:
- Validate the start delimiter (
0x3A). - Validate the address byte matches the device being polled.
- Compute the checksum and compare against the trailing two ASCII hex bytes.
- Extract the numeric payload (skip non-numeric characters).
- Convert the ASCII string to a 32-bit float.
The S7-1200 system library provides a string-to-real conversion String_TO_REAL() in the Conversion Operations group. Use it together with CHARS_TO_STRING() from the String + Char group to slice the buffer.
// Example parser: extract the 5 ASCII chars at offset 4..8 and convert to REAL
IF "dbPtPComm".bRxDone AND "dbPtPComm".bRxError = FALSE THEN
"tmpStr" := CHARS_TO_STRING(IN := P#DB101.DBX4.0 BYTE 5);
"dbPtPComm".rTemperature := STRING_TO_REAL("tmpStr");
"dbPtPComm".bParseOK := TRUE;
ELSE
"dbPtPComm".bParseOK := FALSE;
END_IF;
8. Common Error Codes and Recovery
SEND_PTP and RCV_PTP return a 16-bit STATUS word. The most common values for ASCII mode are listed below. For the complete list, refer to the S7-1200 System Manual Appendix B.
| STATUS (hex) | Meaning | Root Cause | Remediation |
|---|---|---|---|
| 0000 | No error | — | — |
| 7000 | No active job | REQ not set | Verify trigger logic |
| 7001 | Job accepted, executing | — | Wait for DONE/ERROR |
| 7002 | Job rejected, internal busy | Previous job not yet finished | Hold REQ until BUSY rises |
| 8085 | Bad LADDR / HW-ID | Wrong hardware identifier | Check System Constants > HW identifier |
| 8090 | Pointer invalid | SEND or DATA pointer length 0 or wrong area | Verify P# pointer syntax |
| 80A0 | Hardware fault / port not ready | CM 1241 missing, faulty, or not in run | Check module diagnostic LEDs |
| 80A8 | Frame sent but no acknowledgment | Wiring, address, or baud mismatch | Loopback test, swap A/B, verify baud |
| 80B0 | Parity / framing error | Different parity/stop bits on PLC and device | Re-check port configuration on both sides |
| 80B1 | Overrun | CPU cycle time too slow to drain the buffer | Increase OB1 priority, use a smaller buffer, or shorten the cycle |
| 80B2 | Buffer overflow | Receive buffer too small for incoming frame | Increase DATA pointer length |
9. Loopback Test Procedure
Before connecting the temperature controller, validate the PLC hardware and software path with a hardware loopback. This catches 80% of "I can't read anything" faults before they reach the field.
- Wire pin 2 (T/R+) to pin 7 (T/R-) and pin 1 (T/R-) to pin 8 (T/R+) on the CM 1241 9-pin connector — i.e., cross A↔B and short the receive pair. Or use a DB9 gender-changer wired as a loopback.
- Set the
TERMDIP switch toONso the bus is terminated. - Configure the port for 8N1 9600.
- Send a known 8-byte string ("TESTDATA") from a small SCL program. Trigger a one-shot SEND_PTP, then enable RCV_PTP.
- Watch the watch table:
iRcvPTP.DONEmust pulse,STATUS = 0, and the receive buffer atDB101must contain54 45 53 54 44 41 54 41. - If the loopback fails, the issue is hardware (module, cable, DIP switch) or TIA Portal configuration (protocol field set incorrectly). Re-check the device configuration.
10. Field Commissioning Checklist
| # | Check | Pass Criteria |
|---|---|---|
| 1 | CM/CB 1241 is firmly seated; CPU recognizes it | Module visible in online > accessible nodes |
| 2 | Port configured for ASCII, correct baud and frame | Matches controller datasheet exactly |
| 3 | DIP switch TERM = ON at both ends | 120 Ω measured between A and B |
| 4 | Polarity A↔B consistent | PLC T/R+ to controller A+ |
| 5 | Loopback test on the field cable (controller disconnected) | RCV_PTP returns sent bytes |
| 6 | Controller echo test (enable controller's continuous broadcast) | RCV_PTP receives unsolicited frames |
| 7 | Request/response cycle | bTxDone and bRxDone alternate, rTemperature updates |
| 8 | Checksum validation | bParseOK stays TRUE over 1 hour |
| 9 | Long-run soak test (≥ 24 h) | No STATUS errors, no resets |
11. Diagnostic Tools and Watch Tables
Create a watch table with the following tags during commissioning:
// Watch table tags
"dbPtPComm".bSendReq BOOL // Trigger to send
"dbPtPComm".bTxBusy BOOL // SEND_PTP BUSY
"dbPtPComm".bTxDone BOOL // SEND_PTP DONE (one-shot)
"dbPtPComm".wTxStatus WORD // SEND_PTP STATUS
"dbPtPComm".bRxBusy BOOL // RCV_PTP BUSY
"dbPtPComm".bRxDone BOOL // RCV_PTP DONE
"dbPtPComm".wRxStatus WORD // RCV_PTP STATUS
"dbPtPComm".bParseOK BOOL // Parser success flag
"dbPtPComm".rTemperature REAL // Parsed temperature in degC
"iRcvPTP".LEN INT // Bytes actually received
For the receive buffer, create an "observe all" array view in DB101. The S7-1200 CPU stores received bytes sequentially beginning at byte 0. Capture a few hundred milliseconds of buffer activity with a trace; if the buffer shows garbage, the baud or parity is wrong; if the buffer is empty, the controller never received the request — check wiring and address.
12. Multi-Device Bus and Polling Cycle
RS-485 supports up to 32 unit loads (1 UL ≈ 12 kΩ) per bus. For a multi-device bus, address each controller in turn and add a fixed inter-frame delay (≥ 3.5 character times) so that the device can release the bus. A simple sequencer is sufficient:
// State machine: 0=Idle, 1=Sending, 2=Awaiting response, 3=Parsing
CASE "dbPollState".iState OF
0: // Idle: select next device, build request
IF NOT "dbPtPComm".bTxBusy AND NOT "dbPtPComm".bRxBusy THEN
"dbPollState".iAddr := "dbPollState".iAddr + 1;
IF "dbPollState".iAddr > 8 THEN "dbPollState".iAddr := 1; END_IF;
// Build frame for "dbPollState".iAddr into DB100
"dbPtPComm".bSendReq := TRUE;
"dbPollState".iState := 1;
END_IF;
1: // Wait for SEND_PTP DONE
IF "dbPtPComm".bTxDone THEN
"dbPtPComm".bSendReq := FALSE;
"dbPollState".iState := 2;
"dbPollState".tRcvTimeout(IN := FALSE); // preset 100 ms
"dbPollState".tRcvTimeout(IN := TRUE, PT := T#100ms);
END_IF;
2: // Wait for RCV_PTP DONE or timeout
IF "dbPtPComm".bRxDone THEN
"dbPollState".iState := 3;
ELSIF "dbPollState".tRcvTimeout.Q THEN
"dbPollState".iState := 3; // skip this device, go to next
END_IF;
3: // Parse and return to Idle
// Parser runs in OB1 every cycle; just move on
"dbPollState".iState := 0;
END_CASE;
Adjust the inter-request delay (state 0 dwell) to allow the controller to update its value register; 200–500 ms is typical for slow thermal loops.
13. Performance, Timing, and Cycle Budget
At 9600 bit/s, one ASCII character (10 bits including start/stop) is 1.04 ms. A 16-byte request and 24-byte response round-trip is therefore ≈ 41 ms of wire time. With the CPU cycle overhead (typically 5–10 ms at OB1 priority 1) and the RCV_PTP reset pulse (one cycle), a single poll takes ~50 ms. Polling 8 devices on one bus costs 8 × 50 ms = 400 ms, which is well within the 1 s refresh rate required by most temperature control loops.
If the cycle is too long, increase the baud to 38400 or 57600 — most modern temperature controllers support these rates. Avoid going above 38400 on long cable runs without proper termination and biasing.
14. Migration to Modbus RTU
Many new temperature controllers now expose a Modbus RTU interface. If the controller is dual-protocol, switching the CM 1241 from ASCII to Modbus RTU master is straightforward: change the protocol in the port configuration and replace the SEND_PTP/RCV_PTP calls with the standard MB_MASTER instruction. The same buffer logic and parser code can be reused with minimal changes. Refer to the S7-1200 System Manual, Modbus section for the full instruction set and STATUS codes.
15. Frequently Asked Questions
What is the difference between ASCII and Modbus RTU mode on a CM 1241?
ASCII mode uses a character-oriented frame with start and end delimiters (typically ':' and CRLF) and 7- or 8-bit data. Modbus RTU uses a time-silent bus with no delimiters and packs the entire frame as 8-bit binary. RTU is more efficient on the wire (~50% less overhead) but requires tight inter-frame timing. The CM 1241 supports both modes on the same hardware; you change modes by editing the port configuration in TIA Portal.
Why is my RCV_PTP STATUS returning 0x80A8 after I send a request?
STATUS 0x80A8 means the frame was sent but the receiver did not see a valid response. Common causes are A/B polarity swap, baud rate mismatch, address mismatch (the controller ignores requests not addressed to it), or a broken cable. Verify polarity with a multimeter, run a loopback test on the field cable, and confirm the controller's address in its configuration menu.
How do I compute the ASCII checksum for a temperature controller request?
The most common method is the 2's-complement sum of all bytes between the start delimiter and the checksum position. For example, for the frame ':01R', the sum of 0x3A, 0x30, 0x31, 0x52 is 0xF7, the 2's complement is 0x09, and the checksum is the ASCII characters '0' and '9' (0x30 0x39). Always check the controller manual — some vendors use XOR or CRC-8.
Can I use a CB 1241 RS485 module for ASCII communication?
Yes, the CB 1241 RS485 (6ES7241-1CH30-1XB0) supports the ASCII PtP protocol. However, it does not support USS or Modbus RTU mode and has only 2-wire half-duplex. For a single temperature controller on a 2-wire bus it is the most cost-effective solution. For future protocol migration, choose the CM 1241 RS422/485 (6ES7241-1CH32-0XB0) instead.
How do I convert an ASCII numeric string from a temperature controller into a REAL tag?
Use the S7-1200 standard conversion function STRING_TO_REAL from the Conversion Operations group. First slice the relevant bytes from the receive buffer with CHARS_TO_STRING(IN := P#DBxxx.DBXoffset.0 BYTE length), then call the conversion. If the controller uses ',' as the decimal separator, replace it with '.' in a small loop before conversion, because STRING_TO_REAL expects a '.'.
Why does my receive buffer contain garbage characters at higher baud rates?
Garbage on the wire at 38400 bit/s and above is almost always a termination or biasing problem. Enable the CM 1241 internal 120 Ω termination (DIP switch TERM = ON), and if the controller does not bias the bus, add external 620 Ω pull-up/pull-down resistors. Also check that the cable is shielded twisted pair and that the shield is grounded at one end only. Re-measure the bus with an oscilloscope — a clean RS-485 signal should show a 1.5 V to 5 V differential swing, not collapsing to ground between characters.