Python 在Snap7和S7 PLC通信中二进制数据转换

在处理通讯或者网络数据时,例如采用snap7库与西门子PLC通讯时,所传输的多为二进制数据,需要进行相应的处理。python提供了struct模块来完成。这样就可以轻松获取并解析PLC中的数据,便于后续操作。
本文简单介绍struct模块,并结合snap7 举例。

参考文献:
https://blog.csdn.net/evan2008/article/details/8002958
https://blog.csdn.net/qq_30638831/article/details/80421019
https://www.liaoxuefeng.com/wiki/1016959663602400/1017685387246080
https://www.jianshu.com/p/7d2576efdac2
http://blog.sina.com.cn/s/blog_6da124c60102w9te.html

1 struct模块简介

数据在计算机中存储和在网络中传输的方式各有不同。python只定义了6种数据类型,字符串,整数,浮点数,列表,元组,字典。但是C语言中有些字节型的变量,python无法直接处理。

struct 模块用于 Python 值和用 Python 字节对象表示的 C 结构体之间的转换。
给 C 结构打包时一般包含了填充字节(pad bytes),在打/拆包时需考虑对齐的问题。

struct 模块使用 Format Strings 作为 C 结构布局的简洁描述以及与 Python 值的预期转换。

1.1 struct的函数

函数return返回值explain说明
pack(fmt,v1,v2…)string按照给定的格式(fmt),把数据转换成字符串(字节流),并将该字符串返回
pack_into(fmt,buffer,offset,v1,v2…)None按照给定的格式(fmt),将数据转换成字符串(字节流),并将字节流写入以offset开始的buffer中.(buffer为可写的缓冲区,可用array模块)
unpack(fmt,v1,v2……)tuple按照给定的格式(fmt)解析字节流,并返回解析结果
pack_from(fmt,buffer,offset)tuple按照给定的格式(fmt)解析以offset开始的缓冲区,并返回解析结果
calcsize(fmt)size of fmt计算给定的格式(fmt)占用多少字节的内存,注意对齐方式

其中pack和unpack函数使用比较频繁。
fmt为格式,依次为存储结构(大端还是小端),n1数据类型1,n2数据类型2…nm数据类型m
例如:bytes=struct.pack(’!5s2if’,a,b,c,d) ,!大端,5s为5个字符,2i为2个整型int,f为1个float。

1.2 存储结构

CPU存储数据操作的最小单位是一个字节(8个位)。
大端存储模式(Big-Endian),小端存储模式(Little-Endian)是常见的二种字节序。
Little-Endian:低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
Big-Endian:高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
比如0x12345678在内存中的表示形式为:
采用大端模式:
低地址 --------------------> 高地址
0x12 | 0x34 | 0x56 | 0x78
采用小端模式:
低地址 --------------------> 高地址
0x78 | 0x56 | 0x34 | 0x12

Big-Endian是指低地址存放最高有效字节(MSB),而Little-Endian则是低地址存放最低有效字节(LSB)。
一般操作系统采用的都是小端模式,而通讯协议采用大端模式(西门子PLC采用大端模式)。

实际上,由于CPU存储数据操作的最小单位是一个字节,其内部的比特序也分小端和大端。但是我们的程序通过指针访问后得到的数是按照CPU给定的端模式进行读取,字节内部的比特序对于程序来说是不可见的。因此我们只要关心字节序,不需要关心位顺序。

1.3 对齐方式

struct中需要用到的对齐方式如下:
在这里插入图片描述

1.4 格式符

在这里插入图片描述

1.5 函数使用

struct的pack函数把任意数据类型变成bytes:
例如:将无符号整形10240099,PLC输入I0为假,PLC输入I1为真时,转为大端模式二进制数据类型

>>> import struct
>>> struct.pack('>I', 10240099)
b'\x00\x9c@c'
>>>I0=0
>>>I1=1
>>> struct.pack('>I', I0)
b'\x00'
>>>struct.pack('>I', I1)
b'\x01'

在这里插入图片描述
例如将PLC DB块中的float数据12345.6转为二进制
在这里插入图片描述

unpack把bytes变成相应的数据类型:
例如:将 b’\xf0\xf0\xf0\xf0\x80\x80’按照大端模式,分别依次转化为I(4个无符号整型)和H(2个无符号整型)

>>>struct.unpack('>IH', b'\xf0\xf0\xf0\xf0\x80\x80')
(4042322160, 32896)

在这里插入图片描述
将b’F@\xe6f‘转为大端模式的float型

>>>struct.unpack('>f', b'F@\xe6f')
(12345.599609375)

在这里插入图片描述

2 snap7 举例

2.1 连接PLC

现只给出连接python语句。具体设置等细节可以参考《Python-snap7 安装和测试》一文。
PLC IO变量初始值为:

在这里插入图片描述
win+R打开“运行”,输入cmd,确定后,进入DOS命令行终端,输入下面的命令:

python
import snap7
plc=snap7.client.Client()
plc.connect('192.168.0.1',0,1)

在这里插入图片描述

2.2 读取转换I寄存器数据

先用read_area读取I0.0,然后再用struct.unpack获取。
注意读取的PLC数据是bytearray.
具体执行如下图
在这里插入图片描述

2.3 读取转换Q寄存器数据

在这里插入图片描述

2.4 读取转换M寄存器数据

在这里插入图片描述

2.5 读取转换DB块中数据

DB1中DB0.0为float,初始值为:12345.6
在这里插入图片描述

2.6 写入寄存器数据

将I0.0变为Ture
在这里插入图片描述
在这里插入图片描述

2.7 写入DB块中数据

将DB1.DBD0中数据改为65.4321.
在这里插入图片描述
在这里插入图片描述

3 总结

通过Snap7和struct库 可以轻松读取和写入数据(也可以引入snap7源程序中的unit库,get_int,get_float等函数处理),为PLC数据转存到数据库提供了可行的方法。接下来将试着采用sqlite3或MySQL数据库进行存储。
c和c++语言中,读取的为char 字符串。对于整型可以采用IntValue=pUsrData[0]*256+pUsrData[1];而浮点数需要根据其存储结构进行处理,pUsrData[0] 最高位为符号为,pUsrData[0]其他为指数位,pUsrData[1]~pUsrData[3]均为小数点尾数。

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值