前言:
主要使用模块:
import serial
import serial
sendbytes = ' ' # 报文内容
# 连接端口 'com6', 超时0.8,比特率9600、8字节、无校验、停止位1
com = serial.Serial(port="com6", baudrate=9600, timeout=0.8, bytesize=8, parity='N', stopbits=1)
if com.is_open: # 检测端口
print("端口已打开")
# 将hexstr导入bytes对象 报文需要是字节格式
sendbytes = bytes.fromhex(sendbytes)
# 发送报文
com.write(sendbytes)
print(com.readall())
关键点突破:
一、端口设置
二、报文获得
三、报文收发
一、端口设置
1、接线
设备:系统win11、24V直流电源、模拟量输出模块1个、USB转485/232转换器1个、万用表1块
模拟量输出模块 USB转485/232转换器
接线请按照具体说明书
2、端口设置(注意驱动,有些设备需要按照特定驱动)
连接端口 com6, 比特率9600、8字节、无校验、停止位1
二、报文获得
作者通过查询 模拟量输出模块通讯手册如下
01(设备地址)03(读保持寄存器)00 40(起始地址) 00 01(预读取数量) XX XX (校验码,见下)
READ_CH0_AO 01 03 00 40 00 01
READ_CH1_AO 01 03 00 41 00 01
READ_CH2_AO 01 03 00 42 00 01
READ_CH3_AO 01 03 00 43 00 01OUTPUT_CH0_AO 01 06 00 00 00 00
OUTPUT_CH1_AO 01 06 00 01 00 00
OUTPUT_CH2_AO 01 06 00 02 00 00
OUTPUT_CH3_AO 01 06 00 03 00 00ps:校验码 是非常重要的
2、校验码的获取
a.通过 常用的串口调试工具等软件 下方校验按钮 获得
b. python 有例如crcmod的库,可获取对应的CRC校验码
官方文档: crcmod documentation — crcmod v1.7 documentation
c.自写CRC校验码算法文件(难度不大)
# 进制转化实现
class Binary:
"""
自定义进制转化
"""
@staticmethod
def Hex2Dex(e_hex):
"""
十六进制转换十进制
:param e_hex:
:return:
"""
return int(e_hex, 16)
@staticmethod
def Hex2Bin(e_hex):
"""
十六进制转换二进制
:param e_hex:
:return:
"""
return bin(int(e_hex, 16))
@staticmethod
def Dex2Bin(e_dex):
"""
十进制转换二进制
:param e_dex:
:return:
"""
return bin(e_dex)
# 校验方法实现
class CRC:
"""
CRC验证
"""
def __init__(self):
self.Binary = Binary()
def CRC16(self,hex_num):
"""
CRC16校验
"""
crc = '0xffff'
crc16 = '0xA001'
# test = '01 06 00 00 00 00'
test = hex_num.split(' ')
print(test)
crc = self.Binary.Hex2Dex(crc) # 十进制
crc16 = self.Binary.Hex2Dex(crc16) # 十进制
for i in test:
temp = '0x' + i
# 亦或前十进制准备
temp = self.Binary.Hex2Dex(temp) # 十进制
# 亦或
crc ^= temp # 十进制
for i in range(8):
if self.Binary.Dex2Bin(crc)[-1] == '0':
crc >>= 1
elif self.Binary.Dex2Bin(crc)[-1] == '1':
crc >>= 1
crc ^= crc16
# print('crc_D:{}\ncrc_B:{}'.format(crc, self.Binary.Dex2Bin(crc)))
crc = hex(crc)
crc_H = crc[2:4] # 高位
crc_L = crc[-2:] # 低位
return crc, crc_H, crc_L
校验返回结果:
基础报文:01 03 00 40 00 01
完整报文:
01 03 00 40 00 01 85 DE 一般校验码采取低位在前
三、报文收发
import serial
import time
# 基础报文
sendbytes = '01 03 00 40 00 01'
# 生成CRC16校验码
CRC = CRC()
crc, crc_H, crc_L = CRC.CRC16(sendbytes)
# 生成完整报文
sendbytes = sendbytes + ' ' + crc_L + ' ' + crc_H
print(sendbytes)
# 连接端口 'com6', 超时0.8,比特率9600、8字节、无校验、停止位1
com = serial.Serial(port="com6", baudrate=9600, timeout=0.8, bytesize=8, parity='N', stopbits=1)
if com.is_open:
print("port open success")
# 将hexstr导入bytes对象 报文需要是字节格式
sendbytes = bytes.fromhex(sendbytes)
# 发送报文
com.write(sendbytes)
return_res = com.readall()
print(return_res )
打印结果:
['01', '03', '00', '40', '00', '01']
01 03 00 40 00 01 85 de
port open success
b'\x01\x03\x02\x13\x88\xb5\x12'
\x13\x88 可以使用window自带计算器转化以下 16进制 13 88 对应10进制 4000
由于该产品返回值=实际值*1000,所以实际值为4ma, 经过万用表测量电流3.98ma,由于测量误差的存在,该结果没问题
完整代码如下:
# -*- coding: utf-8 -*-
"""
@File : 3.py
@Author : raymood
@Time : 2022/5/6 14:53
@description : NULL
"""
import serial
import time
class Binary:
"""
自定义进制转化
"""
@staticmethod
def Hex2Dex(e_hex):
"""
十六进制转换十进制
:param e_hex:
:return:
"""
return int(e_hex, 16)
@staticmethod
def Hex2Bin(e_hex):
"""
十六进制转换二进制
:param e_hex:
:return:
"""
return bin(int(e_hex, 16))
@staticmethod
def Dex2Bin(e_dex):
"""
十进制转换二进制
:param e_dex:
:return:
"""
return bin(e_dex)
class CRC:
"""
CRC验证
"""
def __init__(self):
self.Binary = Binary()
def CRC16(self, hex_num):
"""
CRC16校验
:param hex_num:
:return:
"""
crc = '0xffff'
crc16 = '0xA001'
# test = '01 06 00 00 00 00'
test = hex_num.split(' ')
print(test)
crc = self.Binary.Hex2Dex(crc) # 十进制
crc16 = self.Binary.Hex2Dex(crc16) # 十进制
for i in test:
temp = '0x' + i
# 亦或前十进制准备
temp = self.Binary.Hex2Dex(temp) # 十进制
# 亦或
crc ^= temp # 十进制
for i in range(8):
if self.Binary.Dex2Bin(crc)[-1] == '0':
crc >>= 1
elif self.Binary.Dex2Bin(crc)[-1] == '1':
crc >>= 1
crc ^= crc16
# print('crc_D:{}\ncrc_B:{}'.format(crc, self.Binary.Dex2Bin(crc)))
crc = hex(crc)
crc_H = crc[2:4]
crc_L = crc[-2:]
return crc, crc_H, crc_L
if __name__ == '__main__':
# 基础报文
sendbytes = '01 03 00 40 00 01'
# 生成CRC16校验码
CRC = CRC()
crc, crc_H, crc_L = CRC.CRC16(sendbytes)
# 生成完整报文
sendbytes = sendbytes + ' ' + crc_L + ' ' + crc_H
print(sendbytes)
# 连接端口 'com6', 超时0.8,比特率9600、8字节、无校验、停止位1
com = serial.Serial(port="com6", baudrate=9600, timeout=0.8, bytesize=8, parity='N', stopbits=1)
if com.is_open:
print("port open success")
# 将hexstr导入bytes对象 报文需要是字节格式
sendbytes = bytes.fromhex(sendbytes)
# 发送报文
com.write(sendbytes)
print(com.readall())
注意:若要不断的进行通讯,请在发送前加上 睡眠延迟