python的modbus-rtu串口通讯

前言:

主要使用模块:

     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

 

  二、报文获得

1、基础知识:​​​​​​Modbus 通讯协议 (RTU传输模式)_csdn_dx的博客-CSDN博客_modbus rtu

 

作者通过查询 模拟量输出模块通讯手册如下

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 01

OUTPUT_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 00

ps:校验码 是非常重要的

2、校验码的获取

 a.通过 常用的串口调试工具等软件 下方校验按钮 获得

b. python 有例如crcmod的库,可获取对应的CRC校验码

官方文档: crcmod documentation — crcmod v1.7 documentation

c.自写CRC校验码算法文件(难度不大) 

算法逻辑:怎么计算crc16校验数据的校验码_qq_37591637的博客-CSDN博客_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())

注意:若要不断的进行通讯,请在发送前加上 睡眠延迟

来源:raymoodlmd

物联沃分享整理
物联沃-IOTWORD物联网 » python的modbus-rtu串口通讯

发表评论