基于UART的自定义通信帧python实现

本文介绍了在项目开发中如何设计和实现基于串口的通信帧,包括通信帧的构成、使用通信帧的目的以及如何通过Python实现在上位机和下位机之间的通信,涉及帧头、命令码、数据长度、CRC校验等内容。
摘要由CSDN通过智能技术生成

简介:最近需要做一个上下位机通信的项目,在和公司对接的时候,需要事先明确通信协议,以便后续的测试。所以我自定义了基于串口的通信协议。

1. 通信帧是什么?为什么要使用通信帧?

通信帧是一种在通信系统中用于传输数据的数据包格式。通信帧是一组按照特定格式组织的二进制数据,其中包含了必要的信息,以便发送方和接收方能够正确地解释和处理数据。通信帧通常包含以下几个重要的部分:

  1. 帧头(Frame Header): 帧头标识了一个通信帧的开始,通常由几个字节组成,用于标记帧的起始位置。

  2. 帧类型/命令码(Frame Type/Command Code): 这个部分指示了帧中包含的数据的类型或者命令的类型。接收方根据这个信息来决定如何解析和处理帧中的数据。

  3. 数据长度(Data Length): 这个部分指示了帧中数据的长度,使接收方能够正确地截取和处理数据。

  4. 数据域(Data Field): 数据域包含了实际传输的数据,其格式和含义由帧类型或者命令码来决定。

  5. 校验(Checksum/CRC): 校验部分用于验证帧中数据的完整性,防止在传输过程中发生错误。常见的校验算法包括CRC(循环冗余校验)和校验和等。

使用通信帧的目的是为了在通信过程中实现可靠、有序、高效的数据传输。通过定义一种标准的帧格式,通信的各个参与方能够按照同样的规则来构造和解析帧,从而保证数据的正确性和一致性。通信帧的使用也使得系统更容易扩展和维护,因为通过修改帧格式,可以相对容易地引入新的功能或者改变通信协议。

2. 自定义通信帧格式

3. 代码实现(基础示例)

        上位机创建自定义通信帧,通过UART传输至下位机。

import serial
import struct
import crcmod.predefined

# 打开串口
ser = serial.Serial('COM1', 9600, timeout=1)

# 创建CRC校验对象
crc16 = crcmod.predefined.Crc('crc-16')

def send_custom_frame(command, data):
    # 帧头
    frame_header = b'\xA5\x5A'
    
    # 命令码
    command_bytes = struct.pack('<H', command)  # 使用'<H'表示小端字节顺序
    
    # 数据长度
    data_length = len(data)
    length_bytes = struct.pack('<H', data_length)
    
    # 计算CRC校验值
    crc16.update(frame_header + command_bytes + length_bytes + data)
    crc_value = crc16.crcValue
    crc_bytes = struct.pack('<H', crc_value)
    
    # 构造自定义通信帧
    frame = frame_header + command_bytes + length_bytes + data + crc_bytes
    ser.write(frame)

# 例子:发送一个带有命令码为0x1234和数据为b'Hello'的帧
send_custom_frame(0x1234, b'Hello')

# 关闭串口
ser.close()

        下位机接收上位机传输的通信帧数据,并且进行解析进行指令对应功能。

import serial
import struct
import crcmod.predefined

# 打开串口
ser = serial.Serial('COM1', 9600, timeout=1)

# 创建CRC校验对象
crc16 = crcmod.predefined.Crc('crc-16')

def receive_custom_frame():
    # 读取帧头
    frame_header = ser.read(2)
    if frame_header != b'\xA5\x5A':
        return None  # 帧头不匹配
    
    # 读取命令码
    command_bytes = ser.read(2)
    command = struct.unpack('<H', command_bytes)[0]  # 使用'<H'表示小端字节顺序
    
    # 读取数据长度
    length_bytes = ser.read(2)
    data_length = struct.unpack('<H', length_bytes)[0]
    
    # 读取数据
    data = ser.read(data_length)
    
    # 读取CRC校验值
    crc_bytes = ser.read(2)
    crc_value = struct.unpack('<H', crc_bytes)[0]
    
    # 验证CRC校验
    crc16.update(frame_header + command_bytes + length_bytes + data)
    if crc16.crcValue != crc_value:
        return None  # CRC校验失败
    
    return command, data

# 例子:接收并解析帧
received_frame = receive_custom_frame()
if received_frame:
    command, data = received_frame
    print("Received Command:", hex(command))
    print("Received Data:", data)

# 关闭串口
ser.close()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值