Python串口实现dk-51e1单相交直流标准源通信

Python实现dk-51e1单相交直流标准源RS232通信

使用RS232,信号源DK51e1的协议帧格式如下:

注意点

配置串口波特率为115200

Check异或和不需要加上第一个0x81的字段

接受终端和发送终端默认的设备ID号都是0

进行直流或交流发送前都必须先打开直流或者交流

给信号源发送直流电压的流程如下:

from DK import DK

dk = DK('COM8')#改成自己的串口号
dk.ConnectS()   #连接串口
dk.openZLDY()   #打开直流电压 电流换成openZLDL()
dk.writeZL(100,0x55)#发送100V直流电压,电流这里改成0x49
# 等待电压发送完毕
user_input = input("按下任意键后关闭\n")
dk.closeZLDY()  #关闭直流电压输出 电流换成 closeZLDL()
dk.CloseSer()   #关闭串口

给信号源发送交流流电压的流程如下:

from DK import DK
import time
dk = DK('COM8')
dk.ConnectS()   #连接串口
dk.openJL()   #打开交流
dk.writeJLDY(100)    #发送100V交流电压
# dk.writeJLDL(10)   #发送10A交流电流
# 等待电压发送完毕
user_input = input("按下任意键后关闭\n")
dk.closeJL()  #关闭交流
dk.CloseSer()   #关闭串口

python实现DK通信的代码如下:

# DK 信号源 DK.py文件
import operator
from functools import reduce
import struct
import serial
import time
from PyQt5.QtCore import QByteArray, QIODevice
import binascii

class DK:
    RS232_Command = {
        'getOs': b'\x81\x00\x00\x07\x00\x4C\x4B', #获取信号源参数
        'closeJLiu': b'\x81\x00\x00\x07\x00\x4F\x48', #关闭交流源 
        'openJLiu' : b'\x81\x00\x00\x07\x00\x54\x53', #打开交流源
        'openZLDY':b'\x81\x00\x00\x08\x00\x67\x55\x3a',# 打开直流源-电压
        'openZLDL':b'\x81\x00\x00\x08\x00\x67\x49\x26',# 打开直流源-电流
        'setZLDY':b'\x81\x00\x00\x09\x00\x66\xff\x55\xc5', #设置直流电压参数
        'setZLDL':b'\x81\x00\x00\x09\x00\x66\xff\x49\xd9', #设置直流电流参数
        'closeZLDY':b'\x81\x00\x00\x08\x00\x68\x55\x35',    #关闭直流电压源
        'closeZLDL':b'\x81\x00\x00\x08\x00\x68\x49\x29',   #关闭直流电流源 

        #切换  直流显示界面         12-30
        'openZLUI':b'\x81\x00\x00\x08\x00\x4A\x06\x44',
         
        #切换  交流显示界面
        'openJLUI':b'\x81\x00\x00\x08\x00\x4A\x01\x43',
        # 显示主界面
        'openMainUI': b'\x81\x00\x00\x08\x00\x4A\x00\x42'
 
        }
    
    btl=115200          #波特率
    def __init__(self,COM) -> None: 
        self.COM=COM 
        pass

#测试信号源的连接
    def Test(self):
        self.ser1.write(self.RS232_Command['getOs'])
        data = self.ser1.readline()  # 读取一行数据
        return str(data)
 
    #串口连接
    def ConnectS(self):
        self.ser1 = serial.Serial(self.COM,self.btl)
        time.sleep(1)
        if self.ser1.isOpen():  # 判断串口是否成功打开
            print("打开串口成功。")
            return True
        else:
            print("打开串口失败。")
            return False
        pass
    # 串口关闭
    def CloseSer(self):
        self.ser1.close()
        pass

    def split_int_to_high_low_bytes(self,num):
        """
        将一个整数分割成高八位和低八位。 
        Returns:
            一个元组,包含高八位和低八位的十六进制表示。
        """
        # 将整数转换为二进制字符串,并补全位数
        binary_str = bin(num)[2:].zfill(8)

        # 分割高低八位
        high_part = binary_str[:4]
        low_part = binary_str[4:]

        # 转换为十六进制
        high_hex = hex(int(high_part, 2))[2:]
        low_hex = hex(int(low_part, 2))[2:]

        return high_hex, low_hex
    
    # 将list中数据依次异或
    def xor_sum(self,arr):
        return reduce(operator.xor, arr)

    # 浮点数打包成四个字节
    def float_to_hex(self,f): 
        # 将浮点数打包成4个字节
        packed = struct.pack('f', f)

        # 将字节转换为十六进制字符串
        hex_str = ''.join('{:02x}'.format(x) for x in packed)

        # 每两个字符一组,并用空格分隔
        hex_groups = ' '.join(hex_str[i:i+2] for i in range(0, len(hex_str), 2))

        return hex_groups
    
    
    def hex_to_decimal(self,hex_string):
        """将十六进制字符串转换为十进制数列表"""
        hex_list = hex_string.split()
        decimal_list = [int(hex_num, 16) for hex_num in hex_list]
        return decimal_list

# =====================================================
# 直流 设置
    
        #关闭直流源电流
    def closeZLDL(self): 
        self.ser1.write(self.RS232_Command['closeZLDL'])
        
    
    # 关闭直流源电压
    def closeZLDY(self):
        self.ser1.write(self.RS232_Command['closeZLDY'])

    # 打开直流设置直流电流
    def openZLDL(self): 
        self.ser1.write(self.RS232_Command['openMainUI']) 
        time.sleep(1)
        self.ser1.write(self.RS232_Command['openZLUI'])     #12-28新增切换ui 
        time.sleep(1)
        self.ser1.write(self.RS232_Command['openZLDL'])
        time.sleep(1)
        self.ser1.write(self.RS232_Command['setZLDL'])
        time.sleep(2)  #打开后必须等五秒再发电流大小
        
        pass

    # 打开直流设置直流电压
    def openZLDY(self):
        self.ser1.write(self.RS232_Command['openMainUI']) 
        time.sleep(1)
        self.ser1.write(self.RS232_Command['openZLUI'])     #12-28新增切换ui 
        time.sleep(1)
        self.ser1.write(self.RS232_Command['openZLDY'])
        time.sleep(1)
        self.ser1.write(self.RS232_Command['setZLDY'])
        time.sleep(2)  #打开后必须等五秒再发电流大小
        pass




# 写入直流值 val1 写入的值 val2是0x55为电压 0x49为电流  
    def writeZL(self , value, value2):
        floats = self.hex_to_decimal( self.float_to_hex(value))
        command=[0x0,0x0,0xd,0x0,0x69,0xFF]
        for f in floats:
            command.append(f)
        command.append( value2 ) 
        checked = self.xor_sum(command)
        command.append( checked )
        commands="129 "
        for comm in command:
            commands=commands+str(comm)+' '
        # print(commands)
        # return commands
        commandstr = commands.split(' ')
       
        numbers =[]
        for comm in commandstr[0:13]:
            numbers.append( int(comm))
        my_bytes = bytes(numbers[0:13]) 
        self.ser1.write(my_bytes) 
        return numbers[0:13]

# =====================================================
# 交流 设置
    
    #打开交流
    def openJL(self):
        self.ser1.write(self.RS232_Command['openMainUI']) 
        time.sleep(1)
        self.ser1.write(self.RS232_Command['openJLUI'])     #12-28新增切换ui  
        time.sleep(1)
        self.ser1.write(self.RS232_Command['openJLiu'])
        time.sleep(1)
    
    # 关闭交流源
    def closeJL(self):
        self.ser1.write(self.RS232_Command['closeJLiu'])
        time.sleep(1)

    # 写入交流电压的值
    
    def writeJLDY(self , value):
        length=11
        floats = self.hex_to_decimal( self.float_to_hex(value))
        command=[0x0,0x0,length,0x0,0x32 ]
        for f in floats:
            command.append(f) 
        checked = self.xor_sum(command)
        command.append( checked )
        commands="129 "
        for comm in command:
            commands=commands+str(comm)+' '
        
        
        commandstr = commands.split(' ')
        
        numbers =[]
        for comm in commandstr[0:length]:
            numbers.append( int(comm))
        # for r in numbers:
        #     print(hex(r))
 
        my_bytes = bytes(numbers[0:length]) 
        self.ser1.write(my_bytes) 
        return numbers[0:length]
    
    # 添加交流电流
    def writeJLDL(self , value):
        length=31
        floats = self.hex_to_decimal( self.float_to_hex(value))
        command=[0x0,0x0,length,0x0,0x32 ]
        for i in range(0,12):
            command.append(0x00)
        for f in floats:            #添加交流电流值
            command.append(f)
        for i in range(0,8):
            command.append(0)

        checked = self.xor_sum(command)     #计算最后一位的出校验位
        command.append( checked )           #把校验位添加到末尾
        commands="129 "                     #所有命令的头部肯定都是0x81==129                     
        for comm in command:
            commands=commands+str(comm)+' '
        commandstr = commands.split(' ')
        numbers =[]
        for comm in commandstr[0:length]:
            numbers.append( int(comm))
         
        my_bytes = bytes(numbers[0:length])     #转换成字节数组发送出去 
        self.ser1.write(my_bytes) 
        return numbers[0:length]