USB 직렬 포트 통신, Raspberry Pi는 GPIO 포트를 사용하여 16진수 배열의 Python 코드를 송수신합니다.

산업용 컴퓨터와 Raspberry Pi는 USB to TTL 직렬 포트 통신을 사용하고 후자는 GPIO 포트를 사용하여 16진수 배열의 Python 코드를 송수신합니다.

배선

USB to TTL 모듈이 사용되고 Linux 시스템의 산업용 컴퓨터는 USB 소켓에 연결되고 TTL 모듈은 RX, TX, VCC 및 GND를 출력하고 Raspberry Pi의 GPIO14 포트는 RXD0의 TX에 연결됩니다. TTL 직렬 포트.

USB-TTL-CH340 모듈

Raspberry Pi에서 Python의 RPi.GPIO 라이브러리를 사용하고 GPIO14(RXD0)를 수신 핀으로 구성합니다.
라즈베리 파이에 데이터 수신을 위한 코드를 작성하고 GPIO.input(14)을 통해 GPIO14(RXD0)의 상태를 확인하여 높으면 데이터 수신이 있다는 의미로 ser.read(ser.in_waiting)를 사용한다. ) 버퍼에서 직렬 포트 수신 데이터를 읽습니다.

동의서

직렬 포트 통신은 uint8 data[6]로 표현되는 총 길이가 6인 16진수 문자 배열과 2개의 헤더를 포함하는 데이터 문자열을 전송합니다. 각 데이터 조각의 처음 2바이트는 0xAA, 0xAA의 시작, 세 번째 바이트는 명령어 유형, 4번째 및 5번째 비트는 2비트 uint8로 인코딩된 명령어, 처음 5비트는 CRC8 6번째 숫자를 얻기 위해 체크하십시오. 사양을 준수하는 일반적인 데이터 형식은 다음과 같습니다.
0xAA , 0xAA , 0x09 , 0x07 , 0x01 , 0x32
0x07 , 0x01 은 코드화된 명령어입니다.

보내다

참조를 위해 지침을 보낼 수 있는 프로그램의 파이썬 버전이 있습니까? 각 하위 기능은 직렬 포트 열기, 명령 보내기, 명령 인코딩, CRC 확인 등과 같은 별도의 기능으로 작성해야 합니다.


다음은 직렬 데이터를 전송하고 명령 인코딩 및 CRC 검사를 수행하는 데 사용되는 ChatGPT 용 샘플 Python 프로그램입니다. 이 프로그램은 직렬 통신을 위해 pyserial 라이브러리를 사용한다고 가정합니다.

# -*- coding: UTF-8 -*-
#!/usr/bin/python3 python3
import serial
import struct
import time


# 配置串口参数
port = '/dev/ttyUSB0'  # 串口设备路径
baudrate = 9600  # 波特率

# 打开串口
ser = serial.Serial(port, baudrate)

# 定义指令类型的常量
INSTRUCTION_TYPE = 0x09

# CRC8校验函数
def crc8(data):
    crc = 0x00
    polynomial = 0x8C  # CRC-8多项式

    for byte in data:
        crc ^= byte
        for _ in range(8):
            if crc & 0x80:
                crc = (crc << 1) ^ polynomial
            else:
                crc <<= 1

    return 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 data


try:
    # 主循环
    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()

encode_instruction()위의 예에서 명령 데이터를 인코딩하는 함수를 정의하고 각 요소를 0-255 범위로 제한하고 인코딩된 데이터를 반환합니다. 그런 다음 명령어를 빌드하고 선행 바이트, 명령어 유형, 인코딩된 명령어 데이터를 추가하고 체크섬을 계산합니다. 마지막으로 함수를 사용하여 ser.write()명령 데이터를 직렬 포트로 보냅니다.

실제 응용 프로그램에서는 안정적이고 신뢰할 수 있는 직렬 통신을 보장하기 위해 오류 처리, 시간 초과 설정, 데이터 처리 등과 같은 기능을 추가해야 할 수도 있습니다. 위의 예는 기본 프레임워크만 제공하며 특정 구현은 특정 요구 사항에 따라 조정 및 확장해야 할 수 있습니다.

인계하다

직렬 포트 통신은 uint8 데이터[6]로 표현되는 총 길이가 6인 16진수 문자 배열과 2개의 헤더를 포함하는 일련의 데이터를 수신합니다. 각 데이터 조각의 처음 2바이트는 0xAA, 0xAA의 시작, 세 번째 바이트는 명령어 유형, 4번째 및 5번째 비트는 인코딩된 명령어로 int16 숫자로 구문 분석해야 합니다. 전면 5자리 체크섬, 6자리 가져오기, MODBUS 알고리즘.

참조할 수 있는 프로그램의 파이썬 버전이 있습니까?
각 하위 기능은 직렬 포트 열기, 명령 수신, 명령 분석, CRC 확인 등과 같은 ChatGPT를 포함하여 별도의 기능으로 작성해야 합니다.

다음은 직렬 포트 데이터 수신, CRC 확인 및 구문 분석 명령을 수행하기 위한 샘플 Python 프로그램입니다. 이 프로그램은 직렬 통신을 위해 pyserial 라이브러리를 사용한다고 가정합니다.

# -*- coding: UTF-8 -*-
#!/usr/bin/python3 python3
import serial
import struct
import RPi.GPIO as GPIO


# 配置GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(14, GPIO.IN)  # GPIO14作为接收引脚

# 配置串口参数
port = '/dev/serial0'  # 树莓派上UART接口所对应的串口设备路径
baudrate = 9600  # 波特率
# 打开串口
ser = serial.Serial(port, baudrate)

# 配置GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(14, GPIO.IN)  # GPIO14作为接收引脚

# 定义指令类型的常量
INSTRUCTION_TYPE = 0x09

# CRC8校验
def crc8(data):
    crc = 0x00
    polynomial = 0x8C  # CRC-8多项式
    
    for byte in data:
        crc ^= byte
        for _ in range(8):
            if crc & 0x80:
                crc = (crc << 1) ^ polynomial
            else:
                crc <<= 1
    
    return crc & 0xFF

# 解析指令
def parse_instruction(data):
    if len(data) != 6:
        print("Invalid instruction length")
        return
    
    # 校验头部
    if data[0] != 0xAA or data[1] != 0xAA:
        print("Invalid header")
        return

    # 校验指令类型
    if data[2] != INSTRUCTION_TYPE:
        print("Invalid instruction type")
        return

    # 校验CRC
    crc = crc8(data[:5])  # 计算校验码时不包括最后一个字节(校验码本身)
    if crc != data[5]:
        print("CRC check failed")
        return
    
    # 获取指令数据
    instruction = data[3:5]
    
    # 执行相应的指令逻辑
    process_instruction(instruction)

# 处理指令逻辑
def process_instruction(instruction):
    # 按照具体需求进行指令处理
    cmd16 = struct.unpack('<h', bytearray(instruction))[0]  # 解析为int16数字
    print("Received Instruction:", cmd16)

try:
    # 接收数据
    while True:
        if GPIO.input(14):  # 检查GPIO14状态,判断是否有数据接收
            # data = ser.read(ser.in_waiting)  # 一直读取数据
            data = ser.read(6)  # 读取固定长度的数据
            # 接收数据
            if len(data) == 6 and data[:2] == b'\xAA\xAA':
                parse_instruction(data)

except KeyboardInterrupt:
    # Ctrl+C被按下,执行异常处理
    
    ser.close()
    print("程序终止,关闭串口")

except Exception as e:
    # 其他异常处理
    
    print("发生异常:", str(e))
    ser.close()

위의 예에서는 parse_instruction()수신된 명령 데이터를 구문 분석하는 함수를 정의했습니다. 먼저 명령어 길이가 6바이트인지 확인하고 CRC 검사를 수행합니다. 확인에 실패하거나 명령 유형이 일치하지 않으면 해당 오류 메시지가 출력됩니다. 확인이 통과되면 명령 데이터를 구문 분석하고 process_instruction()함수를 호출하여 해당 명령 논리를 실행합니다.

위의 예는 기본 프레임워크만 제공하므로 특정 요구 사항에 따라 조정하고 확장해야 할 수도 있습니다. 실제 응용 프로그램에서는 안정적이고 신뢰할 수 있는 직렬 통신을 보장하기 위해 오류 처리, 시간 초과 설정 및 데이터 처리와 같은 기능을 추가해야 할 수도 있습니다.

직렬 통신은 데이터 전송 및 분석 빈도를 어떻게 제어합니까?

채팅GPT

직렬 통신에서는 다양한 방법을 사용하여 데이터 전송 빈도를 제어할 수 있습니다. 다음은 몇 가지 일반적인 방법입니다.

  • 지연된 보내기: 각 패킷을 보내는 사이에 고정 지연을 추가합니다. 기능을 사용하여 time.sleep()패킷 전송 사이에 지연을 추가하여 전송 빈도를 제어할 수 있습니다. 예를 들어 time.sleep(0.1)패킷을 보낸 후 100밀리초 지연됩니다. 이 방법은 권장되지 않습니다.

  • 예약 전송: 타이머를 사용하여 주기적으로 데이터를 전송합니다. Python threading.Timer클래스를 사용하여 타이머를 만들고 타이머 콜백 함수에서 데이터를 보낼 수 있습니다.

직렬 통신에서 threading.Timer제어 데이터 수신 및 분석 빈도를 사용하는 것은 다음 단계를 통해 달성할 수 있습니다.

  • 타이머 객체를 생성하고 타이머 간격을 지정합니다.
  • 타이머 콜백 함수에서 데이터 수신 및 구문 분석 로직을 실행합니다.
  • 콜백 함수를 정기적으로 실행하기 시작하도록 타이머를 시작합니다.

다음은 threading.Timer를 사용하여 직렬 포트 데이터 수신 및 구문 분석의 빈도를 제어하는 ​​방법을 보여주는 예입니다.


import serial
import threading

# 配置串口参数
port = '/dev/ttyUSB0'  # 串口设备路径
baudrate = 9600  # 波特率

# 打开串口
ser = serial.Serial(port, baudrate)

# 定义数据接收和解析的函数
def receive_and_parse_data():
    # 接收数据
    data = ser.readline().strip()

    # 解析数据
    # TODO: 在这里添加你的数据解析逻辑
    print("Received data:", data)

    # 重新启动定时器,控制数据接收和解析的频率
    timer = threading.Timer(1.0, receive_and_parse_data)
    timer.start()

# 启动定时器,控制数据接收和解析的频率
timer = threading.Timer(1.0, receive_and_parse_data)
timer.start()

# 阻塞主线程,保持程序运行
while True:
    pass

# 关闭串口
ser.close()

위의 예에서 receive_and_parse_data()함수는 직렬 포트 데이터를 정기적으로 수신하고 구문 분석하기 위해 타이머에 의해 호출됩니다. 타이머의 간격은 1.0초이며 필요에 따라 조정할 수 있습니다.

지연 전송 또는 타이밍 전송을 사용하는 것과 관계없이 데이터 전송 빈도는 실제 필요에 따라 조정할 수 있습니다. 실제 전송 빈도는 직렬 포트 전송 속도, 패킷 크기 및 대상 장치의 처리 능력과 같은 요인에 의해 제한될 수 있습니다. 따라서 특정 애플리케이션 시나리오 및 요구 사항에 따라 조정하고 테스트해야 합니다.

추천

출처blog.csdn.net/NICAI001/article/details/131617817