1. Introduction to Modbus Protocol Modbus protocol is a universal language used in electronic controllers. Through this protocol, controllers can communicate with each other and with other devices via a network (such as Ethernet). It has become a universal industrial standard. With it, control devices produced by different manufacturers can be connected to an industrial network for centralized monitoring. This protocol defines a message structure that a controller can recognize and use, regardless of the network they communicate through. It describes the process of a controller requesting access to other devices, how to respond to requests from other devices, and how to detect errors and record them. It establishes a common format for the message domain pattern and content. When communicating on a Modbus network, this protocol determines that each controller needs to know their device address, identify the message sent by the address, and decide what action to take. If a response is required, the controller will generate feedback information and send it using the Modbus protocol. On other networks, messages containing the Modbus protocol are converted to the frame or packet structure used on this network. This conversion also expands the method of resolving node addresses, routing paths and error detection based on specific networks. 1. Transmission on the Modbus network The standard Modbus port uses an RS-232C compatible serial interface, which defines the pins, cables, signal bits, transmission baud rate, and parity of the connection port. The controller can be networked directly or via a modem. Controller communication uses master-slave technology, that is, only one device (master device) can initiate transmission (query). Other devices (slave devices) respond accordingly based on the data provided by the master device query. Typical master devices: host and programmable instrument. Typical slave device: programmable controller. The master device can communicate with slave devices alone or with all slave devices in broadcast mode. If communicating alone, the slave device returns a message as a response. If queried in broadcast mode, no response is made. The Modbus protocol establishes the format of the master device query: device (or broadcast) address, function code, all data to be sent, and an error detection field. The slave device response message is also composed of the Modbus protocol, including a field to confirm the action to be taken, any data to be returned, and an error detection field. If an error occurs during the message reception process, or the slave device cannot execute its command, the slave device will build an error message and send it as a response. 2. Transmission on other types of networks On other networks, controllers use peer-to-peer technology to communicate, so any controller can initiate communication with other controllers. In this way, in a single communication process, the controller can act as both a master device and a slave device. The multiple internal channels provided allow simultaneous transmission processes. In the message position , the Modbus protocol still provides the master-slave principle, although the network communication method is "peer". If a controller sends a message, it only acts as a master device and expects a response from the slave device. Similarly, when the controller receives a message, it will build a slave device response format and return it to the sending controller. 3. Query-Response Cycle
(1) Query The function code in the query message tells the selected slave device what function to perform. The data segment contains any additional information about the function to be performed by the slave device. For example, function code 03 requires the slave device to read the holding registers and return their contents. The data segment must contain the information to be told to the slave device: which register to start reading and the number of registers to read. The error detection field provides a way for the slave device to verify that the message content is correct. (2) Response If the slave device generates a normal response, the function code in the response message is a response to the function code in the query message. The data segment includes data collected by the slave device: such as register values or status. If an error occurs, the function code will be modified to indicate that the response message is erroneous, and the data segment contains a code describing this error message. The error detection field allows the master device to confirm whether the message content is usable. 2. Two transmission modes The controller can be set to either of two transmission modes (ASCII or RTU) in standard Modbus network communication. The user selects the desired mode, including serial port communication parameters (baud rate, check method, etc.). When configuring each controller, all devices on a Modbus network must select the same transmission mode and serial port parameters. ASCII mode
: | address | Function Code | Data quantity | Data 1 | ... | Data | LRC high byte | LRC low byte | Enter | Line Break | RTU Mode address | Function Code | Data quantity | Data 1 | ... | Data | CRC high byte | CRC low byte | The selected ASCII or RTU mode is only applicable to standard Modbus networks. It defines each bit of the message segment transmitted continuously on these networks, and determines how to package the information into the message field and how to decode it. On other networks (such as MAP and Modbus Plus), Modbus messages are converted into frames that are unrelated to serial transmission. 1. ASCII mode When the controller is set to communicate in ASCII (American Standard Information Interchange Code) mode on the Modbus network, each 8-bit byte in the message is sent as two ASCII characters. The main advantage of this method is that the time interval between character transmissions can reach 1 second without causing errors. Code system · Hexadecimal, ASCII characters 0...9, A...F · Each ASCII character in the message is a hexadecimal character. Bits that make up each byte · 1 start bit · 7 data bits, the least significant bit is sent first · 1 parity bit, no parity · 1 stop bit (with parity), 2 bits (without parity) Error detection field · LRC (longitudinal redundancy detection) 2. RTU mode When the controller is set to communicate in RTU (remote terminal unit) mode on the Modbus network, each 8-bit byte in the message contains two 4-bit hexadecimal characters. The main advantage of this method is that more data can be transmitted than ASCII at the same baud rate. Code system · 8-bit binary, hexadecimal 0...9, A...F · Each 8-bit field in the message is a two-hexadecimal character bit per byte · 1 start bit · 8 data bits, the least significant bit is sent first · 1 parity bit, no parity if no parity · 1 stop bit (with parity), 2 bits (without parity) Error detection field · CRC (cyclic redundancy check) 3. Modbus message frame In the two transmission modes (ASCII or RTU), the transmitting device converts the Modbus message into a frame with a start and end point, which allows the receiving device to start working at the beginning of the message, read the address allocation information, determine which device is selected (broadcast mode is sent to all devices), and determine when the message has been completed. Partial messages can also be detected and errors can be set as return results. 1. ASCII frame uses ASCII mode, and the message starts with a colon ( character (ASCII code 3AH) and ends with a carriage return line feed character (ASCII code 0DH, 0AH). The transmission characters that can be used in other fields are hexadecimal 0...9, A...F. The devices on the network continuously detect the ":" character. When a colon is received, each device decodes the next field (address field) to determine whether it is sent to itself. The maximum time interval between characters in the message cannot exceed 1 second, otherwise the receiving device will think that the transmission is wrong. A typical message frame is as follows: Start bit | Device Address | Function Code | data | LRC Check | End | 1 character | 2 characters | 2 characters | n characters | 2 characters | 2 characters | Figure 2 ASCII message frame 2. RTU frame Using RTU mode, message transmission must start with a pause interval of at least 3.5 character times. This is easiest to achieve with a variety of character times at the network baud rate (as shown in T1-T2-T3-T4 in the figure below). The first field transmitted is the device address. The transmission characters that can be used are hexadecimal 0...9, A...F. Network devices continuously detect the network bus, including the pause interval. When the first field (address field) is received, each device decodes it to determine whether it is sent to itself. After the last transmission character, a pause of at least 3.5 character times marks the end of the message. A new message can start after this pause. The entire message frame must be transmitted as a continuous stream. If there is a pause time of more than 1.5 character times before the frame is completed, the receiving device will refresh the incomplete message and assume that the next byte is the address field of a new message. Similarly, if a new message starts within less than 3.5 character times after the previous message, the receiving device will consider it to be a continuation of the previous message. This will result in an error, because the value in the final CRC field cannot be correct. A typical message frame is shown below: Start bit | Device Address | Function Code | data | CRC Check | End | T1-T2-T3-T4 | 8Bit | 8Bit | n 8-bit | 16Bit | T1-T2-T3-T4 | Figure 3 RTU message frame 3. Address field The address field of the message frame contains two characters (ASCII) or 8 bits (RTU). Possible slave device addresses are 0...247 (decimal). The address range of a single device is 1...247. The master device selects the slave device by placing the address of the slave device to be contacted in the address field in the message. When the slave device sends a response message, it puts its own address in the address field of the response so that the master device knows which device is responding. Address 0 is used as a broadcast address so that all slave devices can recognize it. When the Modbus protocol is used for a higher level network, broadcasting may not be allowed or replaced in other ways. 4. How to handle the function field The function code field in the message frame contains two characters (ASCII) or 8 bits (RTU). The possible code range is 1...255 in decimal. Of course, some codes are applicable to all controllers, some are applied to certain controllers, and some are reserved for future use. When a message is sent from a master device to a slave device, the function code field tells the slave device what actions to perform. For example, to read the switch status of an input, read the data content of a group of registers, read the diagnostic status of a slave device, allow the program in the slave device to be loaded, recorded, and verified, etc. When the slave device responds, it uses the function code field to indicate whether it is a normal response (no error) or a certain error has occurred (called an objection response). For a normal response, the slave device only responds with the corresponding function code. For an objection response, the slave device returns a code equivalent to the normal code, but the most important position is logical 1. For example: a message sent from the master device to the slave device to read a group of holding registers will generate the following function code: 0 0 0 0 0 0 1 1 (hexadecimal 03H) For a normal response, the slave device only responds with the same function code. For an objection response, it returns: 1 0 0 0 0 0 1 1 (hexadecimal 83H) In addition to the function code being modified due to the objection error, the slave device puts a unique code in the data field of the response message, which can tell the master device what error has occurred. After the master application receives the objection response, the typical processing procedure is to resend the message, or diagnose the message sent to the slave device and report it to the operator. 5. Data field The data field is composed of two sets of hexadecimal numbers, ranging from 00...FF. Depending on the network transmission mode, this can be composed of a pair of ASCII characters or an RTU character. The data field of the message sent from the master to the slave contains additional information: the slave must be used to perform the action defined by the function code. This includes things like non-contiguous register addresses, the number of items to be processed, and the actual number of data bytes in the field. For example, if the master needs to read a group of holding registers from the slave (function code 03), the data field specifies the starting register and the number of registers to be read. If the master writes a group of registers of the slave device (function code 10 hexadecimal), the data field specifies the starting register to be written and the number of registers to be written, the number of data bytes in the data field, and the data to be written to the register. If no error occurs, the data field returned from the slave contains the requested data. If an error occurs, this field contains a objection code that the master application can use to determine the next action to take. In some messages, the data field can be non-existent (0 length). For example, the master device requires the slave device to respond to the communication event record (function code 0B hexadecimal), and the slave device does not need any additional information. 6. Error detection field The standard Modbus network has two error detection methods. The content of the error detection field depends on the selected detection method. ASCII selects the ASCII mode as the character frame, and the error detection field contains two ASCII characters. This is calculated using the LRC (vertical redundancy detection) method on the message content, excluding the initial colon and carriage return line feed. The LRC character is attached to the carriage return line feed. RTU selects the RTU mode as the character frame, and the error detection field contains a 16-bit value (implemented by two 8-bit characters). The content of the error detection field is obtained by performing a cyclic redundancy detection method on the message content. The CRC field is attached to the end of the message, and the low byte is added first and then the high byte. Therefore, the high byte of the CRC is the last byte of the message sent. 7. Continuous transmission of characters When a message is transmitted on a standard Modbus serial network, each character or byte is sent as follows (from left to right): least significant bit...most significant bit When using ASCII character frames, the sequence of bits is: with parity check Start bit | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Parity bit | Stop bits | No parity Start bit | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Stop bits | Stop bits | Figure 4. Bit order (ASCII) When using RTU character frames, the bit sequence is: With parity check Start bit | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Parity bit | Stop bits | No parity Start bit | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Stop bits | Stop bits | Figure 4. Bit order (RTU) 4. Error detection methods The standard Modbus serial network uses two error detection methods. Parity is available for each character, and frame detection (LRC or CRC) is applied to the entire message. They are all generated by the master device before the message is sent, and the slave device detects each character and the entire message frame during reception. The user configures the master device with a predefined timeout interval, which should be long enough for any slave device to react normally. If a transmission error is detected by the slave device, the message will not be received and no response will be made to the master device. In this way, the timeout event will trigger the master device to handle the error. Addresses sent to non-existent slave devices will also cause timeouts. 1. Parity The user can configure the controller to have odd or even parity, or no parity. This will determine how the parity bit in each character is set. If odd or even parity is specified, the number of "1" bits will be counted into the number of bits in each character (7 data bits in ASCII mode and 8 data bits in RTU). For example, the RTU character frame contains the following 8 data bits: 1 1 0 0 0 1 0 1The total number of "1" is 4. If even parity is used, the parity bit of the frame will be 0, so the total number of "1" is still 4. If odd parity is used, the parity bit of the frame will be 1, so the total number of "1" is 5. If the parity bit is not specified, there is no parity bit during transmission, and no parity detection is performed. Instead of an additional stop bit, it is filled into the character frame to be transmitted. 2. LRC detection uses ASCII mode, and the message includes an error detection field based on the LRC method. The LRC field detects the content of the message field except the colon at the beginning and the carriage return line feed at the end. The LRC field is a byte containing an 8-bit binary value. The LRC value is calculated by the transmission device and placed in the message frame. The receiving device calculates the LRC during the message reception process and compares it with the value in the LRC field in the received message. If the two values are not equal, it indicates an error. The LRC method is to continuously accumulate the 8-bit bytes in the message and discard the carry. The simple LRC function is as follows: static unsigned char LRC(auchMsg,usDataLen) unsigned char *auchMsg ; /* Message to be calculated*/ unsigned short usDataLen ; /* Number of bytes to be processed by LRC*/ { unsigned char uchLRC = 0 ; /* LRC byte initialization*/ while (usDataLen--) /* Transmit message*/ uchLRC += *auchMsg++ ; /* Accumulate*/ return ((unsigned char)(-((char_uchLRC))) ; } 3. CRC detection Using the RTU mode, the message includes an error detection field based on the CRC method. The CRC field detects the content of the entire message. The CRC field is two bytes, containing a 16-bit binary value. It is calculated by the transmitting device and added to the message. The receiving device recalculates the CRC of the received message and compares it with the value in the received CRC field. If the two values are different, there is an error. CRC is to first load a 16-bit register with a value of all "1", and then call a process to process the values of the current register of the consecutive 8-bit bytes in the message. Only the 8-bit data in each character is valid for CRC, and the start bit, stop bit and parity bit are invalid. During the CRC generation process, each 8-bit character is individually ORed with the register content, and the result moves toward the least significant bit, and the most significant bit is filled with 0. The LSB is extracted for detection. If the LSB is 1, the register is individually ORed with the preset value. If the LSB is 0, it is not performed. The whole process is repeated 8 times. After the last bit (the 8th bit) is completed, the next 8-bit byte is individually ORed with the current value of the register. The final value in the register is the CRC value after all bytes in the message are executed. When the CRC is added to the message, the low byte is added first, and then the high byte. The simple CRC function is as follows: unsigned short CRC16(puchMsg, usDataLen) unsigned char *puchMsg; /* Message to be CRC checked*/ unsigned short usDataLen ; /* number of bytes in message*/ { unsigned char uchCRCHi = 0xFF ; /* initialize high CRC byte*/ unsigned char uchCRCLo = 0xFF ; /* initialize low CRC byte*/ unsigned uIndex ; /* index in CRC loop*/ while (usDataLen--) /* transmit message buffer*/ { uIndex = uchCRCHi ^ *puchMsgg++ ; /* calculate CRC */ uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex} ; uchCRCLo = auchCRCLo][uIndex] ; } return (uchCRCHi << 8 | uchCRCLo) ; } /* CRC high byte value table*/ static unsigned char auchCRCHi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41 , 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x 00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81 , 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80 , 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81 , 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 }; /* CRC low byte value table*/ static char auchCRCLo[] = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x 99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43 , 0x83, 0x41, 0x81, 0x80, 0x40 } ; |