RFID串口数据解包求助:Python中unpack参数及格式疑问
Let's tackle your two issues one by one: unpacking the RFID reader data correctly and replicating the hexdump -C functionality in Python.
Your frame structure is clearly defined, so we don't need struct.unpack here (that's for binary data like integers or floats) — we can directly slice and decode the ASCII segments once we validate the frame.
First, let's recap your frame format for clarity:
STX (02h) | DATA (10 ASCII) | CHECK SUM (2 ASCII) | CR | LF | ETX (03h)
A complete frame should be 16 bytes long (1 + 10 + 2 + 1 + 1 + 1 = 16). Here's how to process it properly:
import serial import sys try: ser = serial.Serial("/dev/ttyS2", 9600, timeout=1) # Add timeout to avoid hanging except Exception as e: print(f"Connection error: {e}") sys.exit("Failed to connect to device") while True: # Read until we hit the ETX (0x03) to get a complete frame frame = ser.read_until(b'\x03') # Validate the frame to skip corrupted/incomplete data if len(frame) != 16 or frame[0] != 0x02 or frame[-1] != 0x03: print("Skipping invalid/incomplete frame") continue # Extract each component by slicing the byte string stx = frame[0] rfid_data = frame[1:11].decode('ascii') # 10 ASCII characters checksum = frame[11:13].decode('ascii') # 2 ASCII characters cr = frame[13] lf = frame[14] etx = frame[15] # Print the parsed data in a readable format print(f"Parsed RFID Data: {rfid_data}") print(f"Checksum: {checksum}\n")
Key Notes:
- Added a
timeouttoserial.Serialto prevent the loop from hanging if no data comes in. - We first validate the frame length and start/end characters to avoid processing garbage data.
- Since the DATA and CHECK SUM fields are ASCII, we just slice those segments and decode them directly to strings.
hexdump -C in Python You can write a simple function to mimic the output of hexdump -C. This will let you inspect raw serial data just like you do in the command line:
def hexdump(data, width=16): """Mimic the output of hexdump -C""" for offset in range(0, len(data), width): chunk = data[offset:offset+width] # Format the offset as 8-digit hex offset_str = f"{offset:08x}" # Format each byte as 2-digit hex, separated by spaces hex_str = ' '.join(f"{byte:02x}" for byte in chunk) # Pad the hex string to align columns hex_str = hex_str.ljust(width * 3) # Convert bytes to ASCII, replacing non-printable chars with '.' ascii_str = ''.join(chr(byte) if 32 <= byte <= 126 else '.' for byte in chunk) # Print the full line print(f"{offset_str} {hex_str} |{ascii_str}|")
How to Use It:
Call this function with the raw frame data from your serial port:
# Inside your serial loop... frame = ser.read_until(b'\x03') print("Raw Frame Hexdump:") hexdump(frame)
This will output exactly like hexdump -C, showing the offset, hex bytes, and corresponding ASCII characters.
内容的提问来源于stack exchange,提问作者Luca

