# Python 字符串数据(二进制编码数据)格式转换及解析
Python 字符串数据(二进制编码数据)格式转换及解析最近在linux上部署python,希望可以用python来调用串口,同时可以实现数据的格式转换。在python这个做格式化转换不熟悉,花了一点时间研究了一下:一般来说,这种具有普遍需求的东西,python里面应该是自带这些功能的,不然也就没必要使用python来做功能性测试了。首先说需求:我在单片机或者DSP或者FPGA 这些开发板那边采集
Python 字符串数据(二进制编码数据)格式转换及解析
最近在linux上部署python,希望可以用python来调用串口,同时可以实现数据的格式转换。
在python这个做格式化转换不熟悉,花了一点时间研究了一下:一般来说,这种具有普遍需求的东西,python里面应该是自带这些功能的,不然也就没必要使用python来做功能性测试了。
首先说需求:
我在单片机或者DSP或者FPGA 这些开发板那边采集的AD数据,我们一般会通过一些方式(串口/USB 口)给他发送到上位机上来做一些数据分析或者是其他的处理,而一些功能如果让下层的硬件来做的话,这个不是一个好的想法,尤其是在具有密集型的任务的时候,一般就是采集的数据给发送到上位机去做分析和数据处理,以及显示之类的。
本次我是使用了串口来模拟数据的发送,因为串口发送的是标准的字符串数据,我们在上位机接收的时候也是以字符的形式来接收的,但是(中国就是但是多!)我们AD采集的数据或者其他的传感器之类的数据,一般都不是字符串(比如说: 12位数的AD数据发送的时候,一般在单片机先转换为高8位和低8位,不够再高位补0,然后串口先发送高8位,再发送低8位,这样一个完整的AD采样数据就可以发送出去了)
我们在发送的时候就已经知道这2个字节发出去的时候就不是字符串的形式,只不过是通过串口协议发送的。
所以在接收的时候我们就很明确,要对这个数据进行解码得到可阅读的AD数据,所以,在实际解析的时候,要重新拼接组合得到最新的数据格式。
如果你的的上位机用 C/C++来写的,那必然不会存在这个问题,这个是很好解决的(因为 C/C++ 里面有各种字符串的强制转换,所以很好解决)。
但是,我现就是想用python来写,这个就很麻烦了(注:这个是在 python里面的话,基本上都是标准的格式,没有所谓的 unsigned int 8 unsigned int 16)这种,所以会很麻烦。
所以解决这个问题的时候,需要解决解码和格式的转换问题。
然后,就开始找python关于编码的包叫做 struct
可参考学习链接:
#1、csdn模块基本介绍
https://blog.csdn.net/qq_30638831/article/details/80421019
#2、python官方对struct 的介绍
https://docs.python.org/3.9/library/struct.html#format-characters
数据解析方式:
大端小端,一般符合人正常思维的的,就是大端: 如:[ 0x01,0x00 ] -->对该数据拼接,并且转换为 16bit的无符号整型的是 0x0100 --> 256。这个就叫做大端(高位在前,低位在后)。
小端解析的话: 如:[ 0x01,0x00 ] -->对该数据拼接,并且转换为 16bit的无符号整型的是 0x0001 --> 1。这个就叫做小端端(低位在前,高位在后)。
具体什么类型的,自己做个简单的测试就好了,或者双方约定好就行(记不了那么多,直接写个简单代码测试一下更好)
C语言和Python 里面对应的字节数和格式。
python例子如下:
from struct import * # 导入模块
# 导入模块
pack('hhl', 1, 2, 3) # 即数据转换为特定格式的二进制字符串
# b'\x00\x01\x00\x02\x00\x00\x00\x03'
# 数据解包
unpack('hhl', b'\x01\x00\x02\x00\x03\x00\x00\x00') # 二进制字符串转换为其他格式的可读取的数据
#(1, 2, 3) # 数据输出是元组类型
calcsize('hhl') # 计算某种格式所占用的字节数
实际串口的时候,我使用的代码:
import struct # 导入模块
# 将python中的整数(1,2,3),转换为无符号(1字节)的二进制数
date_send = struct.pack('>BBB', 1, 2, 3) # 即格式化数据转换为特定格式的二进制字符串,然后通过串口发送出去
print(date_send)
# 将python中的整数(1,2,3),转换为有符号(1字节)的二进制数
date_send = struct.pack('>bbb', 1, 2, 3) # 即格式化数据转换为特定格式的二进制字符串,然后通过串口发送出去
print(date_send)
# 二进制格式化解析(也可以叫做拆包),我的AD发送的是高位在前,低位在后,所以解析的时候要用大端来解析
struct.unpack('>4H', b'\x01\x00\x02\x00\x03\x00\x00\x00') # 二进制字符串转换为其他格式的可读取的数据
#(256, 512, 768, 0) # 数据输出是元组类型
# 下面是默认的解析,他就是以小端方式来解析的,这个具体使用的时候可以具体分析
struct.unpack('4H', b'\x01\x00\x02\x00\x03\x00\x00\x00') # 二进制字符串转换为其他格式的可读取的数据
#(1, 2, 3, 0)
struct.calcsize('hhl') # 计算某种格式所占用的字节数
# 任意长度的解析:
# 这个一般是用于串口接收的不定长字符串里面的数据解析
# 假设有个需求,把每一个字节都转换为无符号的整型数,但是不知道具体长度
# 如:
recv_date = b'\x01\x00\x02\x00\x03\x00\x00\x00\x00\x02\x30\x02'
A =struct.unpack(str(len(recv_date))+'B', recv_date) # 二进制字符串转换为其他格式的可读取的数据
#(1, 0, 2, 0, 3, 0, 0, 0, 0, 2, 48, 2)
# 打印元组的长度
len(A)
# 12
# 输入的纯字符串转换为二进制数
recv_date = b'123475'
struct.unpack(str(len(recv_date))+'B', recv_date) # 二进制字符串转换为其他格式的可读取的数据
#(49, 50, 51, 52, 55, 53)
# 输入的带中文转换为二进制数(这个会报错),一般不会这么用,我们都是根据实际情况提取我们要的数据,而不是文字,文字的话一般用字符的编码和解码来解决。
recv_date = b'你好,中国'
struct.unpack(str(len(recv_date))+'B', recv_date) # 二进制字符串转换为其他格式的可读取的数据
# SyntaxError: bytes can only contain ASCII literal characters.
更多推荐
所有评论(0)