Python 调用串口通信DLL

Posted 一身转战三千里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 调用串口通信DLL相关的知识,希望对你有一定的参考价值。

#!D:/ide/Python/Python37/
# -*- coding: utf-8 -*-
"""     加载系统相关包    """
import sys
import os
import ctypes
from ctypes import *
from binascii import unhexlify, b2a_hex
from crcmod import mkCrcFun
dll = cdll.LoadLibrary("./UartDll/UartDll.dll")

"""     QT 相关包    """
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QThread, QMutex, QObject, pyqtSignal, QMutexLocker

"""
# @文  件: UartCommuClass.py
# @作  者: 徐生海
# @日  期: 2021/8/26 0026
# @说  明:
"""


class UartSerial(QObject):
    # 打开串口信号
    sign_OpenSerial = pyqtSignal(object, object, object, object, object)
    # 关闭串口信号
    sign_CloseSerial = pyqtSignal()
    # 串口状态信号:用于对外发送
    sign_SerialIsOpen = pyqtSignal(object)
    # 发送串口对象给设备对象
    sign_SendSerialObject = pyqtSignal(QObject)
    # 发送和接收延时
    ReadWriteDelay = int(180)
    # 读取数据延时
    ReadDataDelay = int(5)
    # 当前串口句柄
    CurrentHandle = int(-1)
    # 创建句柄函数
    InitUart = dll.Create
    # 打开串口函数
    OpenUart = dll.Open
    # 关闭串口函数
    CloseUart = dll.Close
    # 发送数据函数
    SendByte = dll.Send
    # 接收数据函数
    ReceiveData = dll.Reveice
    # 发送数据后延时接收函数
    SerSend = dll.SerSend
    # 注消句柄函数
    UnInitUart = dll.UnInit
    # 串口读写锁
    UartMutex: QMutex

    # 串口打开状态
    isOpen = False
    def __init__(self, parent=None):
        super(UartSerial, self).__init__(parent)
        self.isOpen = False
        self.CurrentHandle = -1
        self.UartMutex = QMutex()
        self.InitHandle()
        self.setReadWriteDelay()

    def __del__(self):
        self.UnInitHandle()

    def getHandle(self) -> int:
        return self.CurrentHandle
    # 初始化串口句柄
    def InitHandle(self) -> int:
        self.CurrentHandle = -1
        recH = c_int(-1)
        self.InitUart.argtype = [POINTER(c_int)]
        self.InitUart.restype = c_int
        recD = self.InitUart(byref(recH))
        if recD is 1:
            self.CurrentHandle = recH.value
        return self.CurrentHandle
    # 注消句柄
    def UnInitHandle(self) -> bool:
        self.CloseUart.argtype = [c_int]
        self.CloseUart.restype = c_int
        recD = self.CloseUart(c_int(self.CurrentHandle))
        if recD == 1:
            print("注消句柄成功")
            self.isOpen = False
            self.CurrentHandle = -1
            return True
        else:
            print("注消句柄失败")
            return False
    # 打开串口
    def OpenHandle(self, portName: str, baudRate: int, dataBits=int(8), flowControl=int(0), parity=int(0), stopBits=int(1)) -> bool:
        info = portName + ","
        info += str(baudRate) + ","
        info += str(dataBits) + ","
        info += str(flowControl) + ","
        info += str(parity) + ","
        info += str(stopBits) + ","
        if self.CurrentHandle < 0:
            self.InitHandle()
        byteInfo = info.encode("utf-8")

        self.OpenUart.argtype = [c_int, c_void_p]
        self.OpenUart.restype = c_int
        recD = self.OpenUart(c_int(self.CurrentHandle), byteInfo)
        if recD == 1:
            self.isOpen = True
        else:
            self.isOpen = False
        self.sign_SerialIsOpen.emit(self.isOpen)
        self.sign_SendSerialObject.emit(self)
        return self.isOpen

    # 关闭串口
    def CloseHandle(self) -> bool:
        self.UnInitHandle()
        self.sign_SerialIsOpen.emit(self.isOpen)
        return self.isOpen

    # 发送数据
    def SendHandle(self, Data: str) -> bool:
        Locker = QMutexLocker(self.UartMutex)
        SendBuffer = self.crc16Add(Data)
        SendByteData = bytes.fromhex(SendBuffer)
        if self.CurrentHandle < 0:
            return False
        if not self.isOpen:
            return False
        self.SendByte.argtype = [c_int, c_void_p, c_int]
        self.SendByte.restype = c_int
        recD = self.SendByte(c_int(self.CurrentHandle), SendByteData, c_int(len(SendByteData)))
        if recD != 1:
            return False
        return True
        pass
    # 发送数据延时接收
    def serSend(self, Data: str) -> str:
        Locker = QMutexLocker(self.UartMutex)
        SendBuffer = self.crc16Add(Data)
        SendByteData = bytes.fromhex(SendBuffer)
        if self.CurrentHandle < 0:
            return False
        if not self.isOpen:
            return False
        self.SerSend.argtype = []
        self.SerSend.restype = c_int
        readPtr = create_string_buffer(128)
        readSize = c_int(0)
        self.SerSend.argtype = [c_int, c_void_p, c_int, c_char_p, POINTER(c_int)]
        self.SerSend.restype = c_int
        recD = self.SerSend(c_int(self.CurrentHandle), SendByteData, c_int(len(SendByteData)),
                            pointer(readPtr), byref(readSize))
        if recD != 1:
            return str("")
        return str(readPtr.value, \'utf-8\')

        pass
    # 接收数据
    def Receive(self) -> str:
        Locker = QMutexLocker(self.UartMutex)
        readPtr = create_string_buffer(1024)
        readSize = c_int(0)
        resultStr = str(\'\')
        if self.CurrentHandle < 0:
            return resultStr
        if not self.isOpen:
            return resultStr
        self.ReceiveData.argtype = [c_int, c_void_p, POINTER(c_int)]
        self.ReceiveData.restype = c_int
        recD = self.ReceiveData(c_int(self.CurrentHandle), pointer(readPtr), byref(readSize))
        if recD != 1:
            return resultStr
        resultStr = str(readPtr.value, \'utf-8\')
        return resultStr
        pass

    # 设置延时时长
    def setReadWriteDelay(self, WriteDelay=180, ReadDelay=5) -> bool:
        self.ReadWriteDelay = WriteDelay
        self.ReadDataDelay = ReadDelay
        if self.CurrentHandle < 0:
            return False
        dll.SetDelay.argtype = [c_int, c_int, c_int]
        dll.SetDelay.restype = c_int
        recD = dll.SetDelay(c_int(self.CurrentHandle), c_int(self.ReadWriteDelay), c_int(self.ReadDataDelay))
        if recD != 1:
            return False
        return True
    # CRC16-ModBus
    @staticmethod
    def crc16Add(read) -> str:
        crc16 = mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000)
        data = read.replace(" ", "")
        readout = hex(crc16(unhexlify(data))).upper()
        str_list = list(readout)
        if len(str_list) < 6:
            str_list.insert(2, \'0\' * (6 - len(str_list)))  # 位数不足补0
        crc_data = "".join(str_list)
        read = read.strip() + crc_data[4:] + crc_data[2:4]
        return read

if __name__ == \'__main__\':
    app = QApplication(sys.argv)
    Uart = UartSerial()
    print("初始化后的句柄:", Uart.CurrentHandle)

    result = Uart.OpenHandle("COM1", 115200, 8, 0, 0, 1)
    if result:
        print("打开串口成功")

    for i in range(0, 200):
        result = Uart.SendHandle(str("010300030001"))
        if result:
            recData = Uart.Receive()
            print("发送数据状态:", str("010300030001"), "收到数据:", recData)

 

以上是关于Python 调用串口通信DLL的主要内容,如果未能解决你的问题,请参考以下文章

如何用python写个串口通信的程序

有人会 用python的 pySerial 进行串口通信的吗

python - serial communication(串口通信)

c#串口通信类代码可以直接调用

python串口收包缓存设置

python 如何防止串口通信失败