struct模块中基本的pack和unpack函数:pack(fmt,v1,v2…) 返回string 按照给定的格式(fmt),把数据转换成字符串(字节流),并将该字符串返回.
unpack(fmt,v1,v2…..) 返回tuple 按照给定的格式(fmt)解析字节流,并返回解析结果
格式化字符串:
当打包或者解包的时,需要按照特定的方式来打包或者解包.该方式就是格式化字符串,它指定了数据类型,除此之外,还有用于控制字节顺序、大小和对齐方式的特殊字符.
对齐方式:
为了同c中的结构体交换数据,还要考虑c或c++编译器使用了字节对齐,通常是以4个字节为单位的32位系统,故而struct根据本地机器字节顺序转换.可以用格式中的第一个字符来改变对齐方式.定义如下:
格式符:
最后在此呈上阿凯的二进制Binary_PC发送给ESP32接收的代码【在此请尊重出品:1Z实验室 (1ZLAB: Make Things Easy) 1Z实验室 Make Things Easy . 致力于在机器人+计算机视觉+人工智能的重叠区域, 制作小白友好的教程.】
让大家再糊涂下思维(注意阿凯的是自定义二进制通信协议哦(坏笑,假装我看出来,你没看出来):
PC端 : binary_publisher_pc_pyserial.py
# -*- coding:utf-8 -*-
'''
## 功能描述
# 串口解析信息 二进制数据
## 接线:
# ESP32,TDX,D13 ->ESP32,RXD,D12
'''
from machine import UART,Pin
import struct
import utime
# 初始化串口 UART
# 波特率 115200
# rx -> Pin 13
# tx -> Pin 12
uart = UART(2, baudrate=115200, rx=13,tx=12,timeout=10)
def pack_bin_data(x,y,value):
'''
h: unsigned short bit=2
b: unsigned char (byte): bit =1
i: integer bit=4
f: float bit=4
b*2 + i*2 + f*1
= 1*2 + 4*2 + 4*1 = 14byte
'''
bin_data = struct.pack(">BBiifB",
0xAA,
0xAE,
int(x * 100), # x坐标,精确到小数点后两位
int(y * 100 ), # y坐标,精确到小数点后两位
float(value), # 传感器读入的值,float类型
0x0A) # 结束符 \n = 0x0A
print(bin_data)
return bin_data
x = 100.123
y = -23.398
value = 1.2912312352
while True:
print('Send Data')
print(pack_bin_data(x, y, value))
uart.write(pack_bin_data(x, y, value))
utime.sleep_ms(1000)
print("Recv Data")
# byte_raw = uart.readline()
byte_raw = uart.read()
print(len(byte_raw))
print(byte_raw)
# 讲接收的字节流转换成容易读取的样式
# byte_str = ':'.join(["{:02x}".format(char_byte) for char_byte in byte_raw])
# print(byte_str)
# print(byte_raw)
utime.sleep_ms(1000)
顺带也把下位机ESP32要download进去的的代码:
ESP32端 :binary_listener_esp32_uart.py
# -*- coding:utf-8 -*-
'''
## 功能描述
# 串口解析信息 二进制数据
## 接线:
# ESP32,TDX,D12 -> RXD,CP2102 (USB转TTL)
# ESP32,RXD,D13 -> TXD,CP2102 (USB转TTL)
# TODO 数据解析
# 运行过程中遭遇跳过 ? ESP32的问题
'''
from machine import UART,Pin
import struct
import utime
uart = UART(2, baudrate=115200, rx=16,tx=17,timeout=10)
def depack_bin_data(byte_raw):
'''
将数据解包
根据通信协议,解析数据, 并校验帧头
'''
FRAME_BYTE_LEN = 15
if len(byte_raw) != FRAME_BYTE_LEN:
# 检查数据帧长度是否满足条件
raise ValueError("ERROR: 长度不满足条件")
(verify_byte1, verify_byte2, x, y, value, _) = struct.unpack('>BBiifB', byte_raw)
if verify_byte1 == 0xAA and verify_byte2 == 0xAE:
x /= 100 # 恢复为实际数值范围
y /= 100 # 恢复为实际数值范围
return (x, y, value)
else:
raise ValueError("ERROR: 数据帧头校验失败")
while True:
if uart.any():
print("Recv Raw Data")
byte_raw = uart.readline()
print(byte_raw)
print(len(byte_raw))
# 讲接收的字节流转换成容易读取的样式
# byte_str = ':'.join(['{:02x}'.format(char_byte) for char_byte in byte_raw])
try:
(x, y,value) = depack_bin_data(byte_raw)
print("x= %.2f y=%.2f value=%f"%(x, y, value))
except ValueError as e:
print(e)
# print(byte_raw)
# print('.')
utime.sleep_ms(1000)