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;