python 232串口通信

应某人需求,就发到这里来,说不定有人需要
这段代码用了两年了 暂时没发现多大问题

@2022_10 添加一个使用PYQT的方案,供参考

"""
-*- coding: utf-8 -*-
@Author  : Link
@Time    : 2022/10/21 11:34
@Site    : 
@File    : event_serial.py
@Software: PyCharm
@Remark  : 直接使用QT的信号和槽来操作
"""
import sys
from typing import Union

from PySide2.QtCore import QObject, QByteArray
from PySide2.QtSerialPort import QSerialPort, QSerialPortInfo
from PySide2.QtWidgets import QApplication


class EventRs232(QObject):
    """
    无query写法
    只有写, 和循环读, 读取的数据通过\n来触发事件
    """
    connected: bool = False
    device: QSerialPort = None
    com: str = None
    port: int = 115200
    receive_data: str = ""
    pause = False

    def __init__(self, parent=None, **kwargs):
        super(EventRs232, self).__init__(parent)
        for key, value in kwargs.items():
            setattr(self, key, value)
        self.set_up_serial()

    def __repr__(self):
        return '<%s(%s)><connected? -%s>' % (self.device, self.com, self.connected)

    def set_up_serial(self):
        self.device = QSerialPort()
        self.device.readyRead.connect(self.print)

    def connect_serial(self):
        self.device.setPortName(self.com)
        self.device.setBaudRate(self.port)
        if not self.device.open(QSerialPort.ReadWrite):
            self.connected = False
            print("串口打开失败!")
        self.connected = True

    def disconnect_serial(self):
        self.device.close()
        self.connected = False

    def print(self):
        try:
            receive = bytes(self.device.readAll())
        except Exception as err:
            print(err)
            return
        # 要通过匹配到换行符后, 通过每一行的数据形式来做事件触发
        self.receive_data += receive.decode('UTF-8')
        split_data = self.receive_data.split("\n", 1)
        if split_data.__len__() == 1:
            return
        else:
            line_data = split_data[0]
            self.receive_data = split_data[1]
            """
            对line_data做处理后用信号来驱动
            """
            print(line_data)

    def write(self, data: Union[str, bytes]):
        if isinstance(data, str):
            b_data = data.encode("UTF-8")
        else:
            b_data = data
        self.device.write(QByteArray(b_data))


if __name__ == '__main__':
    app = QApplication(sys.argv)
    stm32 = EventRs232(com="COM7")
    stm32.connect_serial()
    sys.exit(app.exec_())

@使用serail的方案, 可以参考

import serial
import time
from threading import RLock

lock = RLock()
from logger_moudle import logger


class RS232_Device():
    connected = False
    connection = None
    busy = False

    def __init__(self, device_name=None, com=None, port=19200,
                 request=False, hello=None, answer=None, termin=None,
                 timesleep=0.2):
        '''
        返回一个com连接对象
        :param device_name: 设置设备名称
        :param com: 设置com口
        :param request: 设置是否握手:若 Ture,connected 握手后会改变为True
        :param hello: 设置握手发送数据
        :param answer: 设置握手返回数据
        :param termin: 命令 自动加入结束符
        '''
        self.com = com
        self.device_name = device_name
        self.port = port
        self.request = request
        self.hello = hello
        self.answer = answer
        self.termin = termin
        self.timesleep = timesleep

    def __repr__(self):
        return '<%s(%s)><connected? -%s>' % (self.device_name, self.com, self.connected)

    def connect(self):

        if not self.busy:
            try:
                self.connection = serial.Serial(self.com, self.port, bytesize=8, parity='N', stopbits=1, timeout=1)
                if self.request == False:
                    self.connected = True
                logger.warning('%s 打开成功,开启端口为%s,波特率为%s' % (self.device_name, self.com, self.port))
            except serial.serialutil.SerialException as e:
                self.busy = False
                logger.warning('%s 打开失败,端口%s已被开启或无此端口,%s' % (self.device_name, self.com, str(e)))

        if all((self.request, self.connection)):
            if self.answer in self.query(self.hello).encode('utf-8'):
                self.connected = True
                logger.warning('%s 握手成功' % self.device_name)
            else:
                self.connected = False
                logger.warning('%s 通讯失败,请确认端口连接及设备状态!' % self.device_name)

        return self.connected

    def open(self):
        if self.connection:
            try:
                self.connection.open()
                logger.warning('%s 打开成功,开启端口为%s,波特率为%s' % (self.device_name, self.com, self.port))
            except serial.serialutil.SerialException as e:
                self.busy = False
                logger.warning('%s 打开失败,端口%s已被开启或无此端口,%s' % (self.device_name, self.com, str(e)))

    def close(self):
        if self.busy:
            self.connection.close()
            logger.info('%s 通讯成功关闭!' % self.device_name)
            self.busy = False
            self.connected = False

    def get_in_waiting(self):
        time.sleep(self.timesleep)
        return self.connection.read(self.connection.in_waiting)

    def _query(self, value):
        with lock:
            self.get_in_waiting()
            if self.termin:
                value += self.termin
            self.connection.write(value.encode())
            time.sleep(0.05)
            data = self.get_in_waiting().decode('utf-8', 'ignore')
            self.busy = False
            return data

    def query(self, value):
        if self.busy:
            time.sleep(0.05)
            return self.query(value)
        return self._query(value)

    def _write(self, value):
        with lock:
            self.busy = True
            self.get_in_waiting()
            if self.termin:
                value += self.termin
            self.connection.write(value.encode())
            time.sleep(0.05)
            self.busy = False

    def write(self, value):
        if self.busy:
            time.sleep(0.05)
            return self.write(value)
        return self._write(value)

  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值