USB串口通信,树莓派使用GPIO口,收发16进制数组的Python代码

工控机和树莓派采用USB转TTL串口通信,后者使用GPIO口,收发16进制数组的代码 接线
采用USB转TTL模块,Linux系统的工控机接USB插口,TTL模块输出RX、TX、VCC、GND,树莓派的口也就是RXD0接TTL串口的TX 。
在树莓派上使用的RPi.GPIO库,配置(RXD0)作为接收引脚 。
在树莓派上编写接收数据的代码,通过GPIO.input(14)检测(RXD0)的状态,如果为高电平表示有数据接收,然后使用ser.read(ser.)读取串口接收缓冲区中的数据 。
通信协议
串口通信发送一串数据,包含2个头、总长度为6个的16进制字符数组,表示为uint8 data[6] 。每条数据前2个字节是0xAA,0xAA的开头;第3个字节是指令的类型;第4,5位是指令,它被编码为2位的uint8;采用CRC8进制对前面5位校验,得到第6位 。典型符合规范的数据格式如下:
0xAA , 0xAA , 0x09 , 0x07 , 0x01 , 0x32
其中有0x07 , 0x01 是被编码好的指令 。
发送
有无发送指令的版的程序可以参考的 。需要将每个子功能写成单独的函数,包括如打开串口、发送指令、指令的编码、CRC校验等

USB串口通信,树莓派使用GPIO口,收发16进制数组的Python代码

文章插图
以下是一个示例的程序,用于发送串口数据、进行指令编码和CRC校验的过程 。程序假设使用库进行串口通信 。
# -*- coding: UTF-8 -*-#!/usr/bin/python3 python3import serialimport structimport time# 配置串口参数port = '/dev/ttyUSB0'# 串口设备路径baudrate = 9600# 波特率# 打开串口ser = serial.Serial(port, baudrate)# 定义指令类型的常量INSTRUCTION_TYPE = 0x09# CRC8校验函数def crc8(data):crc = 0x00polynomial = 0x8C# CRC-8多项式for byte in data:crc ^= bytefor _ in range(8):if crc & 0x80:crc = (crc << 1) ^ polynomialelse:crc <<= 1return crc & 0xFF# 将时间秒数编码为两位16进制数字def encode_seconds(seconds):seconds_hex = hex(seconds)[2:].zfill(2)# 将秒数转换为两位的十六进制字符串return int(seconds_hex, 16)# 将十六进制字符串转换为整数# 编码指令def encode_instruction(data):encoded_data = []for value in data:encoded_data.append(value & 0xFF)return encoded_data# 发送指令def send_instruction(instruction):# 构建指令data = bytearray()data.extend([0xAA, 0xAA])# 前导字节data.append(INSTRUCTION_TYPE)# 指令类型data.extend(encode_instruction(instruction))# 编码后的指令数据# 计算校验码crc = crc8(data[:5])# 计算校验码时不包括最后一个字节(校验码本身)data.append(crc)# 添加校验码的低字节return datatry:# 主循环while True:# 测试发送指令# instruction = [0x07, 0x08]# 指令数据# 获取当前时间的秒数seconds = int(time.time())# print(seconds)# 发送时间秒数编码instruction = encode_seconds(seconds).to_bytes(4, 'big')# 发送一个字节的数据,高位在前data = send_instruction(instruction[2:4])formatted = ' '.join(f'{byte:02X}' for byte in data)print(formatted)# 发送指令ser.write(data)# # 接收指令# response = receive_command()# if response:#print('Received:', response)# 休眠一段时间,控制发送频率time.sleep(0.2)# 休眠0.2秒except KeyboardInterrupt:# Ctrl+C被按下,执行异常处理ser.close()print("程序终止,关闭串口")except Exception as e:# 其他异常处理print("发生异常:", str(e))ser.close()
在上述示例中,我们定义了一个()函数来对指令数据进行编码,将每个元素限定在0-255的范围内,并返回编码后的数据 。然后我们构建指令,添加前导字节、指令类型、编码后的指令数据,并计算校验码 。最后,我们使用ser.write()函数将指令数据发送到串口 。
请注意,在实际应用中,你可能还需要添加错误处理、超时设置、数据处理等功能,以确保稳定和可靠的串口通信 。以上示例仅提供了一个基本的框架,具体实现可能需要根据你的具体需求进行调整和扩展 。