1.简述

工业控制中一般采用PLC进行一些简单的运动控制和IO控制,很多时候需要PC端能够操作PLC一些数据。在1979年MODICON公司定义了一种工业现场总线协议标准——Modbus(最初的Modbus协议一般是走串口),后来在1996年施耐德公司基于以太网TCP/IP协议重新对MODBUS协议进行定义——MODBUSTCP。

该协议实现了外部设备与PLC进行简单通讯功能,其中主要包括寄存器读取和写入,通过此功能结合PLC内部实现从而实现联合编程目的。
优势:相比于PLC内部的TCP通讯MODBUS直接对PLC寄存器进行操作,更加高效、方便等,无需再在PLC端开通TCP通讯口,一般PLC都会开放一个端口作为MODBUS服务器以供触摸屏等外部设备交互。

三菱PLC较为特殊,可以走MODBUS但是没必要(因为三菱较为NB,自己开发定义了一个比MODBUS更方便的协议SLMP协议),一般三菱PLC网口连接触摸屏都采用SLMP接口(FX5U)

台达PLC通讯建议使用MOUBUSTCP通讯(在这里说一点,台达PLC和三菱比较起来很多功能指令封装较差,但是自由度高,台达编程软件用起来真的难受,强烈推荐三菱GX3【应该本行业里面最在意用户体验最佳的软件】)

另外再说一点,MODBUSRTU协议一般用于串口的MODBUS通讯,其中有一点需要注意是需要加入校验,校验方法为CRC16。具体协议此处不深入。

2.MOUBUSTCP数据组成

MODBUSTCP在TCP发送中数据主要分为两个部分:报文头(MBAP)+帧结构(PDU)。其中报文头由事务处理标识+协议标识+长度+单元标识符,帧结构由功能码+数据组成

最终数据:事务处理标识+协议标识+长度+单元标识符+功能码+数据

事务处理标识
数据序列号,用于区别多次通讯数据(每次加一就好)

协议标识符
表示采用哪种通讯协议,其中MODBUSTCP用00 00表示

长度
后面数据长度(用于保证数据完整性)

单元标识符
设备地址,应该是串口遗留位(没啥用,搞个00就可以了)

功能码
0x01:读线圈
0x05:写单个线圈
0x0F:写多个线圈
0x02:读离散量输入
0x04:读输入寄存器
0x03:读保持寄存器
0x06:写单个保持寄存器
0x10:写多个保持寄存器

数据
读取数据:起始地址(两个byte)+需要读取的数据量(两个byte)
写入单个线圈:地址(两个byte)+请求数据(0xFF00请求输出为ON,0x000请求输出为OFF)

写入多个线圈:起始地址(两个byte)+写入数量(两个byte)+后面字节长度(一个byte)+十六进制表示的线圈值(ox03———11000000)

写入多个寄存器:起始地址(两个byte)+写入数量(两个byte)+后面字节长度(一个byte)+寄存器值(一个寄存器值对应两个字节)

3.实例(验证PLC 台达AS228T)

通过以上介绍看下面的实例(将D0和D1值都改为15):

QByteArray array1;
    array1[0]=0x00;	//事务处理标识
    array1[1]=0x00;
    array1[2]=0x00;	//协议标识
    array1[3]=0x00;
    array1[4]=0x00;	//长度
    array1[5]=0x0B;
    array1[6]=0x01;	//站号
    array1[7]=0x10;	//功能码
    array1[8]=0x00;	//起始地址
    array1[9]=0x00;
    array1[10]=0x00;	//写入长度
    array1[11]=0x02;
    array1[12]=0x04;	//后面数据长度
    array1[13]=0x00;	//首个数据值
    array1[14]=0x0F;
    array1[15]=0x00;	//第二个数据值
    array1[16]=0x0F;

将M0和M1继电器置位

array1[0]=0x00;
    array1[1]=0x00;
    array1[2]=0x00;
    array1[3]=0x00;
    array1[4]=0x00;
    array1[5]=0x08;
    array1[6]=0x01;
    array1[7]=0x0F;
    array1[8]=0x00;
    array1[9]=0x00;
    array1[10]=0x00;
    array1[11]=0x02;
    array1[12]=0x01;
    array1[13]=0x03;