Modbus ASCII Basics: A Beginner's Guide to the Industrial Communication Protocol
This article provides a detailed introduction to the fundamentals of the Modbus ASCII protocol, covering its principles, data format, function code usage, exception handling, and data type conversion. It aims to help beginners quickly master this essential industrial communication protocol and offers practical advice.
Modbus ASCII Basics Tutorial: A Beginner's Guide to the Industrial Communication Protocol
Modbus ASCII is a key transmission mode in the Modbus protocol family. Although less efficient than its sibling, Modbus RTU, it holds a significant place in specific scenarios, such as those requiring manual debugging or transmission through character-based devices, thanks to its human-readable nature. This tutorial is designed to provide you with a comprehensive, from-the-ground-up understanding of the core concepts, working principles, and practical application techniques of the Modbus ASCII protocol.
Whether you are a beginner or an engineer looking to broaden your knowledge, this article will serve as a detailed guide.
1. What is Modbus ASCII?
Modbus ASCII is a transmission mode that uses ASCII (American Standard Code for Information Interchange) characters to exchange data over serial communication lines. Unlike the RTU mode, which sends compact binary data, the ASCII mode converts each byte of data into two printable ASCII characters for transmission. For example, the hexadecimal byte 0x8A is converted into the ASCII string "8A" (the ASCII code for "8" is 0x38, and for "A" is 0x41).
Modbus ASCII also follows the Master-Slave communication model where a Master device initiates requests, and one or more Slave devices respond.
The core features of Modbus ASCII include:
- Human-Readability Since the data is transmitted as ASCII characters, the message content can be directly viewed and understood using a serial monitoring tool, which greatly simplifies debugging and troubleshooting.
- Relaxed Timing Requirements Unlike the strict 3.5-character silence interval required in RTU mode, ASCII mode allows for a gap of up to one second between characters. This makes it better suited for slower or non-real-time communication media, such as certain modems or radio transceivers.
- Clear Frame Boundaries It uses a specific start character (
:) and end characters (carriage returnCRand line feedLF) to define a data frame, making frame identification very clear. - Compatibility Although less efficient, Modbus ASCII provides a reliable communication solution for systems that can only handle text-based data.
2. Physical Layer The Carrier for Modbus ASCII
Similar to Modbus RTU, the Modbus ASCII protocol itself only defines the message structure; its physical transmission relies on standard serial communication interfaces.
2.1 RS-485
RS-485 is the most common choice for industrial applications because it supports multi-point communication, allowing a single master to connect with multiple slave devices. Its differential signal transmission also gives it strong noise immunity and a long transmission distance (up to 1200 meters).
2.2 RS-232
RS-232 is primarily used for point-to-point communication, meaning one master connects to one slave. It has a shorter transmission distance (typically within 15 meters) and weaker noise immunity, making it suitable for short-distance connections or debugging between a device and a local computer.
2.3 Other Media
Due to its relaxed timing requirements between characters, Modbus ASCII is also suitable for special communication media, such as long-distance transmission over telephone line modems or wireless data radios.
3. Modbus Data Model Understanding the Data Storage Structure
Modbus ASCII shares the exact same data model as Modbus RTU. This means that a device's internal data is also abstracted into four logically separate storage areas, each with different data types and access permissions.
| Data Table | Type | Access Rights | Modbus Protocol Address Range | PLC Address Range | Typical Use |
|---|---|---|---|---|---|
| Coils | Single Bit | Read/Write | 0x0000-0xFFFF | 00001-09999 | Control relays, switches, lights, motor start/stop, and other boolean outputs. |
| Discrete Inputs | Single Bit | Read-Only | 0x0000-0xFFFF | 10001-19999 | Read digital input signals, sensor statuses (door open/closed), button states, etc. |
| Holding Registers | 16-bit Word | Read/Write | 0x0000-0xFFFF | 40001-49999 | Store configuration parameters, setpoints, control variables, analog outputs, and internal PLC variables. |
| Input Registers | 16-bit Word | Read-Only | 0x0000-0xFFFF | 30001-39999 | Read measurement values (temperature, pressure), device statuses, sensor data, and analog inputs. |
Important Notes:
- PLC addresses are a common 1-based addressing method in the industrial field, while Modbus protocol addresses are the 0-based addresses actually used in communication. The conversion formula is
Modbus Protocol Address = PLC Address - Base Address. For example, PLC address40003corresponds to the protocol offset address0x0002(40003 - 40001). - The data model's structure is independent of the transmission mode (ASCII or RTU); it is a core part of the Modbus specification.
4. Protocol Structure Modbus ASCII Data Frame
A standard Modbus ASCII data frame is a readable text string. Its structure differs significantly from an RTU frame, but it carries the same core information.
4.1 Data Frame Format Overview
[Start] [Slave Address] [Function Code] [Data Field] [LRC Check] [End]
1 char 2 chars 2 chars N chars 2 chars 2 chars (CR LF)
4.1.1 Start Character - 1 character
- Purpose Clearly marks the beginning of a data frame.
- Content It is always a colon (
:), with an ASCII code of0x3A.
4.1.2 Slave Address - 2 characters
- Purpose Uniquely identifies the target slave device on the network.
- Format An 8-bit slave address (e.g.,
0x0B, or decimal 11) is converted into two ASCII characters ("0"and"B") for transmission. - Range The address range is 1-247. Address
0is the broadcast address.
4.1.3 Function Code - 2 characters
- Purpose Defines the type of operation the master is requesting.
- Format Like the slave address, an 8-bit function code (e.g.,
0x03) is converted into two ASCII characters ("0"and"3") for transmission. - Common Function Codes The list is identical to Modbus RTU, such as
01for reading coils,03for reading holding registers,06for writing a single register, and16(hex0x10) for writing multiple registers.
4.1.4 Data Field - Variable Length
- Purpose Contains the specific information required to execute a function, such as the starting address, number of items, or values to write.
- Format Each byte in the data field is converted into two ASCII characters. Therefore, the length of the data field is twice the number of actual data bytes. For example, to write the 16-bit value
0x12AB, four ASCII characters are transmitted:"1","2","A", and"B".
4.1.5 LRC Check (Longitudinal Redundancy Check) - 2 characters
- Purpose Provides data integrity checking to detect transmission errors. This is the main difference in error checking between Modbus ASCII and RTU.
- Algorithm
- Sum the 8-bit byte values from the Slave Address to the end of the Data Field, ignoring any carries.
- Calculate the two's complement of the result (invert bits and add one) to get an 8-bit LRC value.
- Finally, convert this 8-bit LRC value into two ASCII characters for transmission.
- Difference from CRC LRC is a relatively simple checksum method, and its error detection capability is not as robust as the CRC-16 check used in RTU mode.
- Example C language code
/**
* Calculates the LRC (Longitudinal Redundancy Check) for a Modbus ASCII frame.
* The LRC algorithm sums all bytes from the slave address to the end of the data field,
* ignores any carry, and then takes the two's complement (invert and add one).
*
* @param data Pointer to the data to be calculated.
* @param length The byte length of the data (excluding start and end characters).
* @return The calculated 8-bit LRC checksum value.
*/
unsigned char calculateLRC(const unsigned char *data, int length) {
unsigned char lrc = 0; // Initialize LRC to 0
int i;
// Sum all bytes in the data, ignoring any carry
for (i = 0; i < length; i++) {
lrc += data[i];
}
// Take the two's complement of the result to get the final LRC value
return (unsigned char)(-((char)lrc));
}
4.1.6 End Characters - 2 characters
- Purpose Clearly marks the end of a data frame.
- Content It is always a combination of a carriage return (CR) and a line feed (LF), with ASCII codes
0x0Dand0x0A, respectively.
5. Exception Response Error Handling Mechanism
When a slave receives a valid but unprocessable request (e.g., requesting a non-existent address), it returns an exception response frame. The exception mechanism in Modbus ASCII is similar to that in RTU.
5.1 Exception Response Frame Format
[Start] [Slave Address] [Function Code+0x80] [Exception Code] [LRC Check] [End]
1 char 2 chars 2 chars 2 chars 2 chars 2 chars (CR LF)
- Function Code+0x80 This flags an exception response. The slave sets the most significant bit of the original function code to 1 (by performing a bitwise OR with
0x80) and then converts the result into two ASCII characters. For example, if the request's function code was0x03, the function code field in the exception response would be0x83(ASCII characters"83"). - Exception Code A single byte indicating the specific type of error, also converted into two ASCII characters.
5.2 Common Exception Codes and Their Meanings
| Exception Code (Hex) | Name | Description |
|---|---|---|
| 01 (0x01) | Illegal Function | The function code is not supported by the slave. |
| 02 (0x02) | Illegal Data Address | The requested data address does not exist or is out of range in the slave. |
| 03 (0x03) | Illegal Data Value | The data value in the request is invalid for the slave (e.g., writing a value outside the device's limits). |
| 04 (0x04) | Slave Device Failure | An unrecoverable internal error occurred while the slave was performing the operation. |
| 06 (0x06) | Slave Device Busy | The slave is busy processing another task and cannot respond to the request. |
6. Practical Application Example Understanding the Communication Flow
Specific command and response examples provide a clearer understanding of how Modbus ASCII works.
6.1 Example 1 Read Temperature Sensor Data (Function Code 0x03 - Read Holding Registers)
Suppose we have a temperature sensor at address 1, and its current temperature value is stored in holding register 40001 (protocol offset address 0x0000). We want to read the value of this single register.
Command Sent (Master -> Slave):
:010300000001FB\r\n
Command Breakdown:
:Start character.01Slave address is 1 (ASCII"01"corresponds to hex0x01).03Function code is 3 (ASCII"03"corresponds to hex0x03), for reading holding registers.0000Starting register address is 0x0000.0001Request to read 1 register.FBLRC checksum.- Calculation:
0x01 + 0x03 + 0x00 + 0x00 + 0x00 + 0x01 = 0x05. - Two's complement:
(NOT 0x05) + 1 = 0xFA + 1 = 0xFB.
- Calculation:
\r\nEnd characters (CR LF).
Device Response (Slave -> Master):
:010302006496\r\n
Response Breakdown:
:Start character.01Slave address is 1.03Function code is 3.02Data byte count is 2 (because one 16-bit register was read).0064The actual data read. The ASCII string"0064"corresponds to hex0x0064, which is100in decimal.96LRC checksum.- Calculation:
0x01 + 0x03 + 0x02 + 0x00 + 0x64 = 0x6A. - Two's complement:
(NOT 0x6A) + 1 = 0x95 + 1 = 0x96.
- Calculation:
\r\nEnd characters.
Result The master successfully reads a temperature value of 100.
7. Data Types and Byte Order Handling Complex Data
Modbus ASCII, like RTU, uses 16-bit registers as its basic data unit. Therefore, when handling data types larger than 16 bits (such as 32-bit integers or floating-point numbers), you will encounter issues with byte order and word order.
7.1 Common Data Types
| Data Type | Length (bits) | Registers Used | Description |
|---|---|---|---|
| UINT16 | 16 | 1 | 16-bit unsigned integer (0 to 65,535) |
| INT16 | 16 | 1 | 16-bit signed integer (-32,768 to 32,767) |
| UINT32 | 32 | 2 | 32-bit unsigned integer (0 to 4,294,967,295) |
| INT32 | 32 | 2 | 32-bit signed integer (-2,147,483,648 to 2,147,483,647) |
| FLOAT32 | 32 | 2 | 32-bit single-precision floating-point number (IEEE 754 standard) |
7.2 Byte Order and Word Order Issues
When a single piece of data occupies two registers (like a 32-bit float), the order in which the device arranges these two registers (word order) and the two bytes within each register (byte order) is critical. This is often the primary cause of data parsing errors.
Common combinations include:
- ABCD (Big-Endian) High-order word first, with the high-order byte first within each word.
- DCBA (Little-Endian) Low-order word first, with the low-order byte first within each word.
- BADC (Swapped Big-Endian) High-order word first, with the low-order byte first within each word.
- CDAB (Swapped Little-Endian) Low-order word first, with the high-order byte first within each word.
Solutions:
- Consult the Device Manual This is the first and best way to resolve byte order issues. A device's technical documentation usually specifies its data format.
- Use a Debugging Tool Utilize Modbus software tools that support various byte order parsings to test different combinations until the data is correctly interpreted.
- Programmatic Handling In the master application, perform the necessary byte or word swapping on the received data according to the slave's specification.
8. Modbus ASCII vs. Modbus RTU
The choice of which transmission mode to use depends on the specific application requirements.
| Feature | Modbus ASCII | Modbus RTU |
|---|---|---|
| Data Format | Human-readable ASCII characters | Compact binary data |
| Transmission Efficiency | Lower; each 8-bit data requires 2 characters (14-20 bits) | Higher; each 8-bit data is transmitted in 8 bits (10-11 bits) |
| Frame Delimiting | Uses start character : and end characters CR LF | Uses a silence interval of at least 3.5 character times |
| Character Interval | Allows gaps of up to 1 second | Requires continuous character transmission with intervals not exceeding 1.5 character times |
| Error Check | LRC (Longitudinal Redundancy Check) | CRC-16 (Cyclic Redundancy Check) |
| Error Detection | Relatively weaker | Stronger |
| Debugging Difficulty | Lower | Relatively higher |
| Use Cases | Situations requiring manual monitoring, transmission via modem, or where efficiency is not critical | Most industrial sites and applications requiring high communication efficiency and reliability |
9. Common Problems and Solutions
9.1 No Communication Response
Phenomenon The master sends a request but does not receive any response from the slave.
Common Causes:
- Mismatched Serial Parameters Incorrect settings for baud rate, data bits, stop bits, or parity. Modbus ASCII typically uses 7 data bits with even/odd parity, or 8 data bits with no parity.
- Incorrect Slave Address The requested address does not match the slave's actual configured address.
- Wiring Issues RS-485 A/B lines are reversed or have a poor connection.
- Incorrect Frame Format The start character, end characters, or LRC check is incorrect.
Solutions:
- Carefully check all serial parameters and the Modbus address on both the master and slave sides.
- Inspect the physical connection to ensure wiring is secure and correct.
- Use a serial debugging tool to capture and analyze the transmitted message to confirm it fully complies with the Modbus ASCII specification.
9.2 LRC Check Failure
Phenomenon A response is received, but the calculated LRC does not match the LRC included in the message.
Common Causes:
- Line Noise Electromagnetic interference causes bit errors during transmission.
- Incorrect LRC Calculation The LRC algorithm implementation in the master or slave program is faulty.
- Incomplete Data Frame The beginning or end of the frame is truncated.
Solutions:
- Improve line quality by using shielded twisted-pair cables and ensuring the shield is properly grounded.
- Verify the LRC algorithm by using an online tool or a standard code library to check if your calculation logic is correct.
- Lower the communication speed as reducing the baud rate can enhance communication stability.
9.3 Data Parsing Errors
Phenomenon Communication is successful, but the parsed values are incorrect.
Common Causes:
- Incorrect Byte/Word Order This is the most common issue when handling 32-bit or larger data types.
- Mismatched Data Types Parsing a floating-point number as an integer, or a signed number as an unsigned one.
- Incorrect Address The register address being read does not match the address defined in the device manual.
Solutions:
- Strictly refer to the device manual to confirm the data type, byte order, and address.
- Repeatedly test with debugging software that supports different byte orders until you find the correct combination.
- Double-check the address mapping to ensure the requested address corresponds to the target data point.
10. Summary
Modbus ASCII plays a unique role in the industrial communication landscape with its intuitive, human-readable characteristics. While it may not match the performance of Modbus RTU, it offers indispensable advantages in debugging convenience and adaptability to certain special communication media. After completing this tutorial, you should have:
- Understood the basic concepts of Modbus ASCII and its master-slave communication model.
- Mastered the shared Modbus data model.
- Gained an in-depth understanding of the unique structure of a Modbus ASCII data frame, including its start/end characters and LRC check.
- Learned how to identify and handle exception responses.
- Recognized the importance of data types and byte order and learned their solutions.
- Clarified the key differences between Modbus ASCII and RTU and their respective use cases.