Bootstrap

modbus RTU

1.modbus RTU

1.1 与modbus TCP的区别

在一般工业场景使用modbus RTU的场景还是更多一些,modbus RTU基于串行协议进行收发数据,包括RS232/485等工业总线协议。

与modbus TCP不同的是RTU没有报文头MBAP字段,保留从机地址,在尾部增加了两个CRC检验字节(CRC16),因为网络协议中自带校验,所以在 ModbusTCP协议中不需要使用CRC校验码。

RTU和TCP的总体使用方法基本一致,只是在创建modbus对象时有所不同,TCP需要传入网络socket信息;而RTU需要传入串口相关信息。

1.2 特点

Modbus RTU也是主从问答协议,由主机发起,一问一答

设置串口参数:

设置串口参数时要求:

波特率为9600 bit/s

8位数据位

1位停止位

无流控

2. 格式

ModbusRTU数据帧包含:从站地址码 功能码 数据 校验码

地址码:从机 ID

功能码:同 TCP

数据:起始地址 数量 数据

校验码:2个字节,对 地址码 功能码 数据进行校验,可以通过函数自动生成

3. 报文详解

以03 功能为例

主机--》从机

01 03 00 00 00 0184 0A

01:从机id

03:功能码

00 00:起始地址

00 01:数量

84 0A:CRC校验

从机---》主机

01 03 02 00 14 B4 44

01:从机id

03:功能码

02:字节计数

00 14:数据

B4 44:CRC校验

4. 步骤

步骤:

(1)打开串口文件 open

(2)初始化串口 uart_init

(3)实现功能,从机id 功能码 起始地址 数量

(4)传入数组,生成CRC校验码 GetCRC16

(5)将生成的CRC校验码放入数组,完成拼接

(6)向串口写入数组 write

(7)接收,读串口文件 read

(8)关闭文件描述符

 在虚拟机端写代码实现串口的发送

// 从串口发送数据给从机
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "Crc_Calc.h"

int main(int argc, char const *argv[])
{
    // 1.打开串口文件
    int fd;
    fd = open("/dev/ttyS1", O_RDWR);
    if (fd < 0)
    {
        printf("open error");
        return -1;
    }

    // 2.初始化串口
    uart_init(fd);

    // 3.实现03功能码的某一功能
    // buf:01 03 00 00 00 01
    uint8_t buf[12] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01};

    uint8_t buf1[12] = {0x01, 0x05, 0x00, 0x00, 0xFF, 0x00};

    // 4.根据算法函数,传入数组生成校验码,16位,两个字节
    uint16_t crc = GetCRC16(buf, 6);

    uint16_t crc2 = GetCRC16(buf1, 6);

    // 5.将生成的校验码放入数组,完成拼接
    buf[6] = crc >> 8;
    buf[7] = crc;

    buf1[6] = crc2 >> 8;
    buf1[7] = crc2;

    // 6.发送---向串口文件中写数组
    write(fd, buf, 8);

    // 7.接收---读串口文件
    uint8_t data[128];

    read(fd, data, sizeof(data));

    // 8.打印
    for (int i = 0; i < data[2]; i++)
    {
        printf("%02x ", data[3 + i]);
    }

    printf("\n");

    uint8_t data2[128];
    write(fd, buf1, 8);
    read(fd, data2, sizeof(data2));

    for (int i = 0; i < data2[2]; i++)
    {
        printf("%02x ", data2[3 + i]);
    }
    printf("\n");

    // 9.关闭文件描述符
    close(fd);

    return 0;
}

;