Modbus ASCII is a type of message frame in Modbus. Compared to RTU, ASCII transmission is based on character transmission, and the amount of data transmitted will be larger than that of RTU. Therefore, RTU is generally used when the data volume is large, and ASCII is only used when the data volume is small. Then, the ASCII protocol frame adds start and end, and changes the verification algorithm. Below is a detailed introduction to the ASCII protocol
帧格式
Modbus ASCII 模式下的通讯帧格式如下:
| 名称 | 长度 (字节) | 描述 |
|---|---|---|
| Start | 1 | 以冒号 : 开头,ASCII 十六进制值为 3A |
| Address | 2 | 十六进制节点地址,字符表示 |
| Function | 2 | 十六进制功能码,字符表示 |
| Data | n x 2 | n 是数据字节数,它取决于功能码 |
| LRC | 2 | LRC冗余检验码 |
| End | 2 | CR / LF |
注:地址、功能、数据和 LRC 都是表示 8 位值 (0-255) 的大写十六进制可读字符对;即:在 Modbus ASCII 中,每个数据字节被分割成表示十六进制值中的两个 ASCII 字符的两个字节。
| 组件 | 描述 | 字符数 | ASCII表示 |
|---|---|---|---|
| Start | 消息开始 | 1 CHAR | : |
| Address | 节点地址(十六进制表示) | 2 CHARS | |
| Function | 功能码(十六进制表示) | 2 CHARS | |
| Data | 数据(根据功能码变化,十六进制表示) | n CHARS | |
| LRC CHECK | 纵向冗余检验码(LRC) | 2 CHARS | |
| END | 消息结束,回车换行 | 2 CHARS | CRLF |
在 ASCII 模式下,Modbus 消息的每个部分都以特定的字符数和格式出现,如下所示:
:AA BB CC...DD EE<CRLF>
:- 消息的开始符号。AA- 节点地址,十六进制表示。BB- 功能码,十六进制表示。CC...DD- 数据字段,根据功能码和需要传输的数据长度变化。EE- LRC 校验码,用于错误检测。<CRLF>- 消息的结束符号,代表回车和换行(Carriage Return Line Feed)。

ASCII帧的传输状态

上面状态图可以得到的信息:
1)“空闲” 态是没有发送和接收报文要处理的正常状态。
2)每次接收到 ":" 字符表示新的报文的开始。如果在一个报文的接收过程中收到该字符,则当前地报文被认为不完整并被丢弃。而一个新的接收缓冲区被重新分配。
3)检测到帧结束后,完成 LRC 计算和检验。然后,分析地址域以确定帧是否发往此设备,如果不是,则丢弃此帧。 为了减少接收处理时间,地址域可以在一接到就分析,而不需要等到整个帧结束。
ASCII帧的报文传输
由于ASCII报文帧与RTU报文帧有着很大的不同,ASCII报文帧是有起始和结束标识符的,而RTU帧没有这样的标识。所以ASCII报文帧的接收就简单方便多了,也不需要什么t3.5的帧间隔时间。
但是呢,为了保证接收的报文帧连续,还是可以约定字符间的传输时间的。一般认为,报文中的字符时间间隔可以达到一秒,如果超过了这个时间间隔,就认为发生了错误,要废弃掉这一帧报文数据,重新开始接收。
功能码
ASCII 模式下最常用的功能代码与 RTU 模式下的功能代码定义相同。以下是一些基本的功能码及其描述:
| 访问地址 | 映射地址 | 描述 | 功能 | R/W |
|---|---|---|---|---|
| 1 ~ 10000 | address-1 | Coils | 01/05/15 | R/W |
| 10001 ~ 20000 | address-10001 | Discrete Inputs | 02 | R |
| 30001 ~ 40000 | address-30001 | Input Registers | 04 | R |
| 40001 ~ 50000 | address-40001 | Holding Registers | 03/06/16 | R/W |
ASCII传输示例
例如,要读取地址 0x20C1 的两个寄存器,需要发送以下 ASCII 消息:
:010420C1000218<CRLF>
请求:
:- 消息开始 - 0x3A01- 从站地址 - 0x0104- 功能码 (读取输入寄存器) - 0x0420C1- 要读取的寄存器地址 - 0x20C10002- 要读取的寄存器长度 (必须是 2) - 0x000218- LRC 校验码<CRLF>- 消息结束,回车换行 - 0x0D0A
响应:
:01040400001234B1<CRLF>
响应:
:- 消息开始 - 0x3A01- 从站地址 - 0x0104- 功能码 (读取输入寄存器) - 0x0404- 读取数据长度 (4 字节) - 0x0400001234- 从 VAR1 读取的值 - 0x00001234B1- LRC 校验码<CRLF>- 消息结束,回车换行 - 0x0D0A
常用功能码操作
以下是 Modbus 的常用功能码及其请求和响应示例:
功能 01(01H)读线圈
- 请求:读取从机中线圈的 ON/OFF 状态。

- 响应:线圈状态响应消息被打包为数据字段的每比特表示一个线圈。

功能 02(02H)读离散输入
- 请求:读取从机中离散输入的 ON/OFF 状态。

- 响应:离散输入状态响应消息的构造与线圈状态相同。

功能 03(03H)读保持寄存器
- 请求:读取从机中保持寄存器的二进制内容。

- 响应:保持寄存器数据在每个寄存器中打包为两个字节。

功能 04(04H)读输入寄存器
- 请求:读取从机中输入寄存器的二进制内容。

- 响应:读输入寄存器数据的响应消息的构造与读取保持寄存器相同。

功能 05(05H)写单线圈
- 请求:将单个线圈写入 ON 或 OFF。

- 响应:正常的响应是请求的回显。

功能 06(06H)写单个保持寄存器
- 请求将一个值写入单个保持寄存器中。当广播时,该函数在所有附加的从机上设置相同的寄存器引用。请求消息指定要写入的寄存器引用(指定地址和数值)。

- 响应

功能 15(0FH)写多个线圈
- 请求:将一个线圈序列中的每个线圈写入 ON 或 OFF。

- 响应:正常响应返回从地址、功能代码、起始地址和写入的线圈数量。

功能 16(10H)写多个保持寄存器
- 请求:将值写入到一个保持寄存器序列中。

- 响应:正常响应返回从地址、功能代码、起始地址和写入的寄存器数量。

LRC校验
LRC 校验码的计算方法如下:
unsigned char ucMBLRC( unsigned char * pucFrame, unsigned short usLen )
{
unsigned char ucLRC = 0; /* LRC char initialized */
while( usLen-- )
{
ucLRC += *pucFrame++; /* Add buffer byte without carry */
}
/* Return twos complement */
ucLRC = ( UCHAR ) ( -( ( CHAR ) ucLRC ) );
return ucLRC;
}
Leave a Reply