我们以S7的1500系列来查看握手和读取、写入【字Word或者位Bit】命令报文
以下报文不做说明时都是十六进制字节。
西门子PLC需要连接成功后发送两次握手命令方可进行读写通信。
西门子PLC的S7协议的头由四个字节组成.。
第一个字节数固定为03,第二个字节数固定为00
第三个字节和第四个字节代表【报文字节总长度】,比如00 16就代表报文总长度为22
报文字节总长度=256*buffer[2]+buffer[3]
【高字节在前,低字节在后】,而在C#程序中是低字节在前,高字节在后的。
因此,对报文的解析是 通过 03 00 开头,然后查找第三个和第四个字节,来获取【报文字节总长度】,然后依次查找【报文字节总长度-4】个字节即终止。
S7协议的地址(偏移量)是按照位来运算的,因此需要地址值乘以8。
地址的三个字节范围为0x000000~0x08FFFF
比如M30000,实际地址就是30000*8=240000,然后转化为3个字节。
240000=0x03A980,对应三个字节【03 A9 80】
比如DB21234.40000 其中DB号21234为0x52F2,DB编号对应两个字节【52 F2】
偏移量(地址)40000乘以8就是320000,也就是0x04E200,对应三个字节【04 E2 00】
第一次握手First Handshake
发送命令【22个字节】:
03 00 00 16 11 E0 00 00 00 01 00 C0 01 0A C1 02 01 02 C2 02 01 00
反馈命令【22个字节】:
03 00 00 16 02 D0 80 32 01 00 00 02 00 00 08 00 00 F0 00 00 01 00
第二次握手Second Handshake
发送命令【25个字节】:
03 00 00 19 02 F0 80 32 01 00 00 04 00 00 08 00 00 F0 00 00 01 00 01 01 E0
反馈命令【27个字节】:
03 00 00 1B 02 F0 80 32 01 00 00 02 00 00 08 00 00 00 00 00 01 00 01 00 F0 00 F0
读取报文命令解析:
发送报文解析:
固定报文头:buffer[0]=0x03,buffer[1]=0x00
报文长度(字节个数):buffer[2]=0x00,buffer[3]=0x1F 【报文长度=256*buffer[2]+buffer[3]】
固定协议标识:buffer[4]=0x02,buffer[5]=0xF0,buffer[6]=0x80,buffer[7]=0x32
发送命令:buffer[8]=0x01
冗余标识(保留):buffer[9]=0x00,buffer[10]=0x00,buffer[11]=0x00,buffer[12]=0x01
读取命令长度:【报文长度-17】,即从索引17开始,有多少个字节
buffer[13]=0x00,buffer[14]=0x0E
读取内部数据时为00,读取CPU型号为数据长度 buffer[15]=0x00,buffer[16]=0x00
读写指令,04读,05写: buffer[17]=0x04
读取数据块个数: buffer[18]=0x01
下面每12个字节作为一个数据块:
{
指定有效值类型 buffer[19]=0x12
接下来本次地址访问长度 buffer[20]=0x0A
语法标记ANY, buffer[21]=0x10
按字为单位02,按位为单位01 buffer[22]=0x02
访问数据的字节个数 buffer[23]=0x00,buffer[24]=0x02
DB块编号,M区为0 buffer[25]=0x00,buffer[26]=0x00
访问区域标识:buffer[27]=0x83【M区为0x83,DB块为0x84】
偏移位置:buffer[28]=0x00,buffer[29]=0x03,buffer[30]=0x20 【偏移量最大为0x07FFFF】
偏移量计算方式 :
M区地址需要乘以8.比如 M100=100*8=800=0x0320,
DB块偏移量乘以8. 比如DB30000.12000 DB块号30000=0x7530,偏移位置需要乘以8,即12000*8=96000=0x017700
}
反馈(接收)报文解析:
按字读取:从索引21开始查找 反馈数据开始标记 0xFF04,然后读取2个字节的长度,0x5BA0,即十进制 23456
按位读取:从索引21开始查找 反馈数据开始标记 0xFF03,然后读取一个字节的长度,具体值为0x01,即为true
写入报文命令解析:
发送报文解析:
固定报文头:buffer[0]=0x03,buffer[1]=0x00 报文长度(字节个数):buffer[2]=0x00,buffer[3]=0x25 【报文长度=35+字节数组个数】
固定协议标识:buffer[4]=0x02,buffer[5]=0xF0,buffer[6]=0x80,buffer[7]=0x32
发送命令:buffer[8]=0x01
标识序列号:buffer[9]=0x00,buffer[10]=0x00,buffer[11]=0x00,buffer[12]=0x01
固定:buffer[13]=0x00,buffer[14]=0x00
写入长度:写入长度+4 因从索引31开始计算,故为length+4 buffer[15]=0x00,buffer[16]=0x06
读写指令,04读,05写 buffer[17]=0x05,
写入数据块个数 buffer[18]=0x01
下面共12个字节作为一个数据块:
{
指定有效值类型 buffer[19]=0x12
接下来本次地址访问长度 buffer[20]=0x0A
语法标记ANY, buffer[21]=0x10
按字为单位02,按位为单位01 buffer[22]=0x02
访问数据的字节个数 buffer[23]=0x00,buffer[24]=0x02
DB块编号,M区为0 buffer[25]=0x00,buffer[26]=0x00
访问区域标识:buffer[27]=0x83【M区为0x83,DB块为0x84】
偏移位置:buffer[28]=0x07,buffer[29]=0x79,buffer[30]=0x90 【偏移量最大为0x07FFFF】
偏移量计算方式 :
M区地址需要乘以8.比如 M61234=61234*8=489872=0x077990,
DB块偏移量乘以8. 比如DB30000.12000 DB块号30000=0x7530,偏移位置需要乘以8,即12000*8=96000=0x017700
}
按字写入:buffer[31]=0x00,buffer[32]=0x04,如果按位写入,则buffer[32]=0x03
按位计算长度:即字节长度*8 buffer[33]=0x00,buffer[34]=0x10
具体写入的字节数据:buffer[35]=0x7A,buffer[36]=0x02
反馈(接收)报文解析:
最后一个字节是0xFF代表写入成功,否则失败
下面是具体命令报文示例:
读取M区和DB块,按字读取
发送命令【读取M100的short值【23456】】:
03 00 00 1F 02 F0 80 32 01 00 00 00 01 00 0E 00 00 04 01 12 0A 10 02 00 02 00 00 83 00 03 20
反馈命令:
03 00 00 1B 02 F0 80 32 03 00 00 00 01 00 02 00 06 00 00 04 01 FF 04 00 02 5B A0
发送命令【DB30000.12000的short值【12345】】:
03 00 00 1F 02 F0 80 32 01 00 00 00 01 00 0E 00 00 04 01 12 0A 10 02 00 02 75 30 84 01 77 00
反馈命令:
03 00 00 1B 02 F0 80 32 03 00 00 00 01 00 02 00 06 00 00 04 01 FF 04 00 02 30 39
读取M区和DB块,按位读取
发送命令【M61236读取bool为true】:
03 00 00 1F 02 F0 80 32 01 00 00 00 01 00 0E 00 00 04 01 12 0A 10 01 00 01 00 00 83 07 79 A0
反馈命令:
03 00 00 1A 02 F0 80 32 03 00 00 00 01 00 02 00 05 00 00 04 01 FF 03 00 01 01
发送命令【DB12345.65432.3读取bool为true】:
03 00 00 1F 02 F0 80 32 01 00 00 00 01 00 0E 00 00 04 01 12 0A 10 01 00 01 30 39 84 07 FC C3
反馈命令:
03 00 00 1A 02 F0 80 32 03 00 00 00 01 00 02 00 05 00 00 04 01 FF 03 00 01 01
写入M区和DB块,按字写入
发送命令【M56789的Int32为987654321】:
03 00 00 27 02 F0 80 32 01 00 00 00 01 00 0E 00 08 05 01 12 0A 10 02 00 04 00 00 83 06 EE A8 00 04 00 20 3A DE 68 B1
反馈命令:
03 00 00 16 02 F0 80 32 03 00 00 00 01 00 02 00 01 00 00 05 01 FF
发送命令【DB23789.36789的Int32为-1234567890】:
03 00 00 27 02 F0 80 32 01 00 00 00 01 00 0E 00 08 05 01 12 0A 10 02 00 04 5C ED 84 04 7D A8 00 04 00 20 B6 69 FD 2E
反馈命令:
03 00 00 16 02 F0 80 32 03 00 00 00 01 00 02 00 01 00 00 05 01 FF
写入M区和DB块,按位写入
发送命令【M51133.0写入true】:
03 00 00 24 02 F0 80 32 01 00 00 00 01 00 0E 00 05 05 01 12 0A 10 01 00 01 00 00 83 06 3D E8 00 03 00 01 01
反馈命令:
03 00 00 16 02 F0 80 32 03 00 00 00 01 00 02 00 01 00 00 05 01 FF
发送命令【DB23789.36789.2写入true】:
03 00 00 24 02 F0 80 32 01 00 00 00 01 00 0E 00 05 05 01 12 0A 10 01 00 01 5C ED 84 04 7D AA 00 03 00 01 01
反馈命令:
03 00 00 16 02 F0 80 32 03 00 00 00 01 00 02 00 01 00 00 05 01 FF