[Diaoye learns programming] MicroPython manual's built-in module struct: Packaging and unpacking of binary data

Insert image description here

MicroPython is a lightweight version of the interpreter designed to run the Python 3 programming language in embedded systems. Compared with regular Python, the MicroPython interpreter is small (only about 100KB) and is compiled into a binary Executable file to run, resulting in higher execution efficiency. It uses a lightweight garbage collection mechanism and removes most of the Python standard library to accommodate resource-constrained microcontrollers.

The main features of MicroPython include:
1. The syntax and functions are compatible with standard Python, making it easy to learn and use. Supports most of Python's core syntax.
2. Directly access and control the hardware, control GPIO, I2C, SPI, etc. like Arduino.
3. A powerful module system that provides functions such as file system, network, and graphical interface.
4. Support cross-compilation to generate efficient native code, which is 10-100 times faster than the interpreter.
5. The amount of code is small, and the memory usage is small, which is suitable for running on MCU and development boards with small memory.
6. Open source license, free to use. The Shell interactive environment provides convenience for development and testing.
7. The built-in I/O driver supports a large number of microcontroller platforms, such as ESP8266, ESP32, STM32, micro:bit, control board and PyBoard, etc. There is an active community.

The application scenarios of MicroPython include:
1. Quickly build prototypes and user interactions for embedded products.
2. Make some small programmable hardware projects.
3. As an educational tool, it helps beginners learn Python and IoT programming.
4. Build smart device firmware to achieve advanced control and cloud connectivity.
5. Various microcontroller applications such as Internet of Things, embedded intelligence, robots, etc.

Pay attention to the following when using MicroPython:
1. The memory and Flash space are limited.
2. The explanation and execution efficiency is not as good as C language.
3. Some library functions are different from the standard version.
4. Optimize the syntax for the platform and correct the differences with standard Python.
5. Use memory resources rationally and avoid frequently allocating large memory blocks.
6. Use native code to improve the performance of speed-critical parts.
7. Use abstraction appropriately to encapsulate underlying hardware operations.

Generally speaking, MicroPython brings Python into the field of microcontrollers, which is an important innovation that not only lowers the programming threshold but also provides good hardware control capabilities. It is very suitable for the development of various types of Internet of Things and intelligent hardware.

Insert image description here
MicroPython's built-in module struct is a module for packing and unpacking primitive data types, which can be used to convert between bytes objects and other data types. Its main features are:

1. It can use the compile() method to compile a format string into a struct object to improve the efficiency and reusability of packaging and unpacking.
2. It can pack and unpack between byte objects and tuples using the pack() and unpack() methods, or pack and unpack between byte objects and buffers using the pack_into() and unpack_from() methods Bag.
3. It can use the calcsize() method to calculate the number of bytes required for a given format string, or use the iter_unpack() method to iteratively unpack multiple tuples on a bytes object.
4. It supports some commonly used size/byte order prefixes, such as @, <, >, !, etc., to specify the size and alignment of data.
5. It supports some commonly used format codes, such as b, B, h, H, i, I, l, L, q, Q, s, P, f, d, etc., to specify the type and length of data.

Application scenarios of the struct module include:

1. Used to perform some binary data processing or analysis tasks, such as reading and writing files, network communication, protocol analysis, etc.
2. Used to implement some complex data structures or logic, such as bit fields, bitmaps, checksums, etc.
3. Used to learn or teach some knowledge or skills related to binary data, such as byte order, data alignment, data compression, etc.

The precautions for the struct module are:

1. The struct module implements a subset of the CPython module12, and does not support spaces in the format string12, so it is not fully compatible with the functions and performance of CPython.
2. The struct module provides direct and unrestricted access and control of binary data, improper use may result in data errors, corruption or loss. Use caution and follow relevant regulations and guidelines.
3. The callback function used by the struct module is executed in the interrupt context 132. It needs to be as short and fast as possible, and avoid complex or time-consuming operations, so as not to affect system performance and stability.

The following are several practical application examples of MicroPython's built-in module struct:

Case 1: Use the struct module to read the header information of a BMP file

# 导入struct模块
import struct

# 打开一个BMP文件
f = open('image.bmp', 'rb')

# 读取文件头部14个字节,并解包为一个元组
file_header = struct.unpack('<2sIHHI', f.read(14))

# 打印文件头部信息
print('File type:', file_header[0]) # 文件类型
print('File size:', file_header[1]) # 文件大小
print('Reserved 1:', file_header[2]) # 保留字段1
print('Reserved 2:', file_header[3]) # 保留字段2
print('Offset:', file_header[4]) # 偏移量

# 读取位图信息头部40个字节,并解包为一个元组
bitmap_header = struct.unpack('<IHHIIIIHHIIII', f.read(40))

# 打印位图信息头部信息
print('Header size:', bitmap_header[0]) # 头部大小
print('Width:', bitmap_header[1]) # 图像宽度
print('Height:', bitmap_header[2]) # 图像高度
print('Planes:', bitmap_header[3]) # 颜色平面数
print('Bits per pixel:', bitmap_header[4]) # 每像素位数
print('Compression:', bitmap_header[5]) # 压缩方式
print('Image size:', bitmap_header[6]) # 图像大小
print('X pixels per meter:', bitmap_header[7]) # 水平分辨率
print('Y pixels per meter:', bitmap_header[8]) # 垂直分辨率
print('Colors used:', bitmap_header[9]) # 使用的颜色数
print('Important colors:', bitmap_header[10]) # 重要的颜色数

# 关闭文件
f.close()

Case 2: Use the struct module to construct a TCP data packet

# 导入struct模块
import struct

# 定义一个TCP数据包的格式字符串
tcp_format = '!HHIIHHHH'

# 定义一个TCP数据包的各个字段的值
source_port = 1234 # 源端口号
destination_port = 80 # 目的端口号
sequence_number = 1000 # 序列号
acknowledgment_number = 0 # 确认号
data_offset = 5 # 数据偏移
reserved = 0 # 保留字段
flags = 2 # 标志位,表示SYN
window_size = 65535 # 窗口大小
checksum = 0 # 校验和
urgent_pointer = 0 # 紧急指针

# 使用pack()方法将各个字段打包为一个字节对象
tcp_packet = struct.pack(tcp_format, source_port, destination_port, sequence_number, acknowledgment_number, (data_offset << 12) | (reserved << 6) | flags, window_size, checksum, urgent_pointer)

# 打印打包后的字节对象
print(tcp_packet)

Case 3: Use the struct module to parse the binary representation of a floating point number

# 导入struct模块
import struct

# 定义一个浮点数的值
x = 3.14

# 使用pack()方法将浮点数打包为一个字节对象,使用'f'格式代码表示单精度浮点数,使用'>'前缀表示大端字节序
x_bytes = struct.pack('>f', x)

# 打印打包后的字节对象,以十六进制显示每个字节的值
print(x_bytes.hex())

# 使用unpack()方法将字节对象解包为一个元组,使用'I'格式代码表示无符号整数,使用'>'前缀表示大端字节序
x_int = struct.unpack('>I', x_bytes)[0]

# 打印解包后的整数值,以二进制显示每一位的值,使用format()方法指定32位长度和前缀'0b'
print(format(x_int, '032b'))

# 根据IEEE 754标准,单精度浮点数由1位符号位,8位指数位和23位尾数位组成,因此可以使用位运算和移位运算来提取各个部分的值
sign = (x_int >> 31) & 1 # 符号位为最高位,右移31位并与1按位与得到符号位的值
exponent = (x_int >> 23) & 0xff # 指数位为次高8位,右移23位并与0xff按位与得到指数位的值
mantissa = x_int & 0x7fffff # 尾数位为最低23位,与0x7fffff按位与得到尾数位的值

# 打印各个部分的值,以二进制显示每一位的值,使用format()方法指定长度和前缀'0b'
print('Sign:', format(sign, '01b'))
print('Exponent:', format(exponent, '08b'))
print('Mantissa:', format(mantissa, '023b'))

Case 4: Packing and unpacking data:

import struct

# 打包数据
packed_data = struct.pack('i f s', 42, 3.14, b'Hello')
print("Packed Data:", packed_data)

# 解包数据
unpacked_data = struct.unpack('i f s', packed_data)
print("Unpacked Data:", unpacked_data)

In this example, we use the struct module to pack and unpack data. We use the pack() function to pack data into a byte stream in a specified format. Here, we're packing an integer 42, a float 3.14, and a byte string b'Hello'. Then, we use the unpack() function to unpack the packed byte stream into raw data. Finally, we print out the packed and unpacked data.

Case 5: Processing binary file data:

import struct

# 读取二进制文件
with open('data.bin', 'rb') as file:
    # 读取4字节的整数
    data = file.read(4)
    value = struct.unpack('i', data)[0]
    print("Value:", value)

In this example, we use the struct module to read data from a binary file. We open a binary file named data.bin and read 4 bytes of data using the read() method. Then, we use the unpack() function to unpack the read bytes into an integer. Finally, we print out the integer value read.

Case 6: Convert data to network byte order:

import struct
import socket

# 将整数转换为网络字节序
value = 12345
network_byte_order = socket.htonl(value)
packed_data = struct.pack('!L', network_byte_order)
print("Packed Data:", packed_data)

In this example, we use the struct module to convert integers to network byte order. First, we convert the integer value 12345 to network byte order using the socket module's htonl() function. Then, we use the pack() function to pack the converted network byte order into an unsigned long integer data. Here, we use !L to represent network byte order and unsigned long. Finally, we print out the packed data. These practical application examples demonstrate the capabilities of using MicroPython's built-in module struct. By using the struct module, you can pack and unpack data, process binary file data, and perform operations such as byte order conversion. These functions are very useful in scenarios such as interacting with underlying data, network communication, and binary data processing.

Case 7: Pack data into binary format

import struct

# 定义数据
name = "Alice"
age = 25
height = 1.65

# 使用 struct.pack() 打包数据
packed_data = struct.pack("5sif", name.encode(), age, height)

# 打印打包后的二进制数据
print("打包后的数据:", packed_data)

In this example, we use the struct.pack() function to pack the data into binary format. We define a string type name, an integer type age, and a floating point type height. Use the format string "5sif", where "5s" represents a string of length 5, "i" represents an integer, and "f" represents a floating point number. We convert the name to a byte string using the encode() method and then pass the data to the struct.pack() function. The packed binary data will be printed.

Case Eight: Unpacking Data from Binary Data

import struct

# 定义二进制数据
packed_data = b'\x41\x6c\x69\x63\x65\x00\x00\x00\x19\x00\x00\xb0?\x00\x00\x00\x00'

# 使用 struct.unpack() 解包数据
unpacked_data = struct.unpack("5sif", packed_data)

# 打印解包后的数据
name, age, height = unpacked_data
print("解包后的数据:")
print("姓名:", name.decode())
print("年龄:", age)
print("身高:", height)

In this example, we have a piece of packed binary data packed_data. Using the struct.unpack() function, we can unpack the original data from the binary data. We use the same format string "5sif" as in the previous example for unpacking. The unpacked data will return a tuple, which we can split into the variables name, age, and height. We convert name to a string using the decode() method and print out the unpacked data.

Case 9: Calculating the checksum

import struct

# 定义数据
data = [10, 20, 30, 40, 50]

# 计算校验和
checksum = sum(data) & 0xFF

# 使用 struct.pack() 打包校验和
packed_checksum = struct.pack("B", checksum)

# 打印打包后的校验和
print("打包后的校验和:", packed_checksum)

In this example, we have a set of data, which contains some integers. We compute the checksum of this data, sum the data using the sum() function, and use bitwise & 0xFF to limit the result to one byte. We then use the struct.pack() function to pack the checksum into a one-byte binary format. The packed checksum will be printed.

These examples show the struct module in action in MicroPython. You can modify and extend it according to your needs.

Insert image description here

Guess you like

Origin blog.csdn.net/weixin_41659040/article/details/132776910