固件中有modbusRtu的库吗?
# -*- coding: UTF-8 -*-
# 导入模块 & 全局变量
import utime
from machine import UART
import ubinascii as binascii
from usr import EventMesh, Common
# | 参数 | 参数类型 | 说明 | 类型 |
# | -------- | ------- | ------------------ | -------- |
# | CRITICAL | 常量 | 日志记录级别的数值 50 | critical |
# | ERROR | 常量 | 日志记录级别的数值 40 | error |
# | WARNING | 常量 | 日志记录级别的数值 30 | warning |
# | INFO | 常量 | 日志记录级别的数值 20 | info |
# | DEBUG | 常量 | 日志记录级别的数值 10 | debug |
# | NOTSET | 常量 | 日志记录级别的数值 0 | notset |
Grey_log = Common.LogAdapter("ModBus")
Grey_log.log_service.logtimeflag = True # 设置LOG时间输出: True; False.
Grey_log.log_service.LEVEL = Common.LOG_LV.INFO # 设置LOG输出等级: DEBUG; INFO;
# 串口信息
_uartport = UART.UART2 # 串口
_baudrate = 4800 # 波特率
_databits = 8 # 数据位
_parity = 0 # 校验
_stopbit = 1 # 停止位
_flowctl = 0 # 流控
_control_485 = UART.GPIO1 # 485切换引脚
_device_address = 0x01 # 设备地址
# 功能码
READ_COILS = 0x01 # 读线圈
READ_DISCRETE_INPUTS = 0x02 # 读离散量输入
READ_HOLDING_REGISTERS = 0x03 # 读保持寄存器
READ_INPUT_REGISTER = 0x04 # 读输入寄存器
WRITE_SINGLE_COIL = 0x05 # 写单个线圈
WRITE_SINGLE_REGISTER = 0x06 # 写单个寄存器
READ_EXCEPTION_STATUS = 0x07 # 读取异常状态
DIAGNOSTICS = 0x08 # 诊断
GET_COM_EVENT_COUNTER = 0x0B # 获取com事件计数器
GET_COM_EVENT_LOG = 0x0C # 获取com事件LOG
WRITE_MULTIPLE_COILS = 0x0F # 写多个线圈
WRITE_MULTIPLE_REGISTERS = 0x10 # 写多个寄存器
REPORT_SERVER_ID = 0x11 # 报告服务器ID
READ_FILE_RECORD = 0x14 # 读文件记录
WRITE_FILE_RECORD = 0x15 # 写文件记录
MASK_WRITE_REGISTER = 0x16 # 屏蔽写寄存器
READ_WRITE_MULTIPLE_REGISTERS = 0x17 # 读/写多个寄存器
READ_FIFO_QUEUE = 0x18 # 读取FIFO队列
READ_DEVICE_IDENTIFICATION = 0x2B # 读设备识别码
# 异常码
SUCCESSFUL = 0x00 # 成功
ILLEGAL_FUNCTION = 0x01 # 非法功能
ILLEGAL_DATA_ADDRESS = 0x02 # 非法数据地址
ILLEGAL_DATA_VALUE = 0x03 # 非法数据值
SERVER_DEVICE_FAILURE = 0x04 # 从站设备故障
ACKNOWLEDGE = 0x05 # 确认
SERVER_DEVICE_BUSY = 0x06 # 从属设备忙
MEMORY_PARITY_ERROR = 0x08 # 存储奇偶性差错
GATEWAY_PATH_UNAVAILABLE = 0x0A # 不可用网关路径
DEVICE_FAILED_TO_RESPOND = 0x0B # 网关目标设备响应失败
SLAVE_ADDR_ERROR = 0xFC # 从地址错误
CRC_ERROR = 0xFD # CRC校验错误
RECEIVE_ERROR = 0xFE # 接收数据异常, 非ModBus标准错误
SEND_ERROR = 0xFF # 发送数据异常, 非ModBus标准错误
CRC16_TABLE = (
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601,
0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0,
0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81,
0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941,
0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01,
0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0,
0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081,
0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00,
0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0,
0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981,
0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41,
0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700,
0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0,
0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281,
0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01,
0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1,
0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80,
0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541,
0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101,
0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0,
0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481,
0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801,
0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1,
0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581,
0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341,
0x4100, 0x81C1, 0x8081, 0x4040)
class ModbusInit:
def __init__(self, uartport, baudrate, databits, parity, stopbit, flowctl, rt_pin):
self.uart = UART(uartport, baudrate, databits, parity, stopbit, flowctl)
self.uart.control_485(rt_pin, 1)
@staticmethod
def divmod_low_high(addr): # 分离高低字节
high, low = divmod(addr, 0x100)
# Grey_log.debug("addr:0x{:04X} high:0x{:02X} low:0x{:02X}".format(addr, high, low))
return high, low
def calc_crc(self, string_byte): # 生成CRC
crc = 0xFFFF
for pos in string_byte:
crc ^= pos
for i in range(8):
if (crc & 1) != 0:
crc >>= 1
crc ^= 0xA001
else:
crc >>= 1
gen_crc = hex(((crc & 0xff) << 8) + (crc >> 8))
int_crc = int(gen_crc, 16)
return self.divmod_low_high(int_crc)
@staticmethod
def split_return_bytes(ret_bytes): # 将字符串转换二进制
ret_str = binascii.hexlify(ret_bytes, ',') # 二进制转字符串, 以','分隔.
return ret_str.split(b",") # 转换为列表, 以','分隔.
def read_uart(self): # UART接收
num = self.uart.any()
msg = self.uart.read(num)
# Grey_log.debug('UART接收数据: ')
# for i in range(num):
# Grey_log.debug('0x{:02X}'.format(msg[i]))
# ret_str = binascii.hexlify(msg, ',') # 二进制转字符串, 以','分隔.
ret_str = self.split_return_bytes(msg)
Grey_log.debug('UART接收数据: {}'.format(ret_str))
return msg
def write_uart(self, slave, const, start, *coil_qty): # UART发送
start_h, start_l = self.divmod_low_high(start)
data = bytearray([slave, const, start_h, start_l])
coil_qty_h = bytearray(len(coil_qty))
coil_qty_l = bytearray(len(coil_qty))
for i in range(len(coil_qty)):
coil_qty_h[i], coil_qty_l[i] = self.divmod_low_high(coil_qty[i])
data += bytearray([coil_qty_h[i], coil_qty_l[i]])
# Grey_log.debug(data)
crc = self.calc_crc(data)
# Grey_log.debug("crc_high:0x{:02X} crc_low:0x{:02X}".format(crc[0], crc[1]))
for num in crc:
data.append(num)
self.uart.write(data)
# Grey_log.debug('UART发送数据: ')
# dataLen = len(data)
# for i in range(dataLen):
# Grey_log.debug('0x{:02X}'.format(data[i]))
ret_str = self.split_return_bytes(data)
Grey_log.debug('')
Grey_log.debug('-------------------------------------------------------------------------')
Grey_log.debug('UART发送数据: {}'.format(ret_str))
return True
def read_holding_registers(self, slave_addr, starting_addr, register_qty):
if self.write_uart(slave_addr, READ_HOLDING_REGISTERS, starting_addr, register_qty):
utime.sleep_ms(200)
retstr = self.read_uart()
if len(retstr) > 4:
retstr_temp = retstr[0:-2]
retstr_crc = self.calc_crc(bytearray(retstr_temp))
if ((retstr_crc[0]==retstr[-2])and(retstr_crc[1]==retstr[-1])):
if retstr[0] == slave_addr:
if retstr[1] == READ_HOLDING_REGISTERS:
if retstr[2] == (register_qty*2):
ret_str = self.split_return_bytes(retstr[3:-2])
Grey_log.info('读取寄存器数据: {}'.format(ret_str))
Grey_log.info('--------------------------------------------------------------------------')
return retstr[3:-2]
else:
Grey_log.error('Error Code: 0x{:02X}'.format(ILLEGAL_DATA_VALUE))
Grey_log.error('-------------------------------------------------------------------------')
return ILLEGAL_DATA_VALUE
else:
Grey_log.error('Error Code: 0x{:02X}'.format(ILLEGAL_FUNCTION))
Grey_log.error('-------------------------------------------------------------------------')
return ILLEGAL_FUNCTION
else:
Grey_log.error('Error Code: 0x{:02X}'.format(SLAVE_ADDR_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return SLAVE_ADDR_ERROR
else:
Grey_log.error('Error Code: 0x{:02X}'.format(CRC_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return CRC_ERROR
else:
Grey_log.error('Error Code: 0x{:02X}'.format(RECEIVE_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return RECEIVE_ERROR
else:
Grey_log.error('Error Code: 0x{:02X}'.format(SEND_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return SEND_ERROR
def write_single_register(self, slave_addr, register_address, register_value):
if self.write_uart(slave_addr, WRITE_SINGLE_REGISTER, register_address, register_value):
utime.sleep_ms(200)
retstr = self.read_uart()
if len(retstr) > 4:
retstr_temp = retstr[0:-2]
retstr_crc = self.calc_crc(bytearray(retstr_temp))
if ((retstr_crc[0]==retstr[-2])and(retstr_crc[1]==retstr[-1])):
if retstr[0] == slave_addr:
if retstr[1] == WRITE_SINGLE_REGISTER:
if (retstr[2]==(register_address>>8))and(retstr[3]==(register_address&0xFF))and(retstr[4]==(register_value>>8))and(retstr[5]==(register_value&0xFF)):
Grey_log.info('写入单个寄存器成功')
Grey_log.info('--------------------------------------------------------------------------')
return SUCCESSFUL
else:
Grey_log.error('Error Code: 0x{:02X}'.format(ILLEGAL_DATA_VALUE))
Grey_log.error('-------------------------------------------------------------------------')
return ILLEGAL_DATA_VALUE
else:
Grey_log.error('Error Code: 0x{:02X}'.format(ILLEGAL_FUNCTION))
Grey_log.error('-------------------------------------------------------------------------')
return ILLEGAL_FUNCTION
else:
Grey_log.error('Error Code: 0x{:02X}'.format(SLAVE_ADDR_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return SLAVE_ADDR_ERROR
else:
Grey_log.error('Error Code: 0x{:02X}'.format(CRC_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return CRC_ERROR
else:
Grey_log.error('Error Code: 0x{:02X}'.format(RECEIVE_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return RECEIVE_ERROR
else:
Grey_log.error('Error Code: 0x{:02X}'.format(SEND_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return SEND_ERROR
def write_multiple_registers(self, slave_addr, starting_address, *register_values):
if self.write_uart(slave_addr, WRITE_MULTIPLE_REGISTERS, starting_address, *register_values):
utime.sleep_ms(200)
retstr = self.read_uart()
if len(retstr) > 4:
retstr_temp = retstr[0:-2]
retstr_crc = self.calc_crc(bytearray(retstr_temp))
if ((retstr_crc[0]==retstr[-2])and(retstr_crc[1]==retstr[-1])):
if retstr[0] == slave_addr:
if retstr[1] == WRITE_MULTIPLE_REGISTERS:
register_values_len = len(register_values)
register_values_len_H , register_values_len_L = self.divmod_low_high(register_values_len)
if (retstr[2]==(starting_address>>8))and(retstr[3]==(starting_address&0xFF))and(retstr[4]==register_values_len_H)and(retstr[5]==register_values_len_L):
Grey_log.info('写入多个寄存器成功')
Grey_log.info('--------------------------------------------------------------------------')
return SUCCESSFUL
else:
Grey_log.error('Error Code: 0x{:02X}'.format(ILLEGAL_DATA_VALUE))
Grey_log.error('-------------------------------------------------------------------------')
return ILLEGAL_DATA_VALUE
else:
Grey_log.error('Error Code: 0x{:02X}'.format(ILLEGAL_FUNCTION))
Grey_log.error('-------------------------------------------------------------------------')
return ILLEGAL_FUNCTION
else:
Grey_log.error('Error Code: 0x{:02X}'.format(SLAVE_ADDR_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return SLAVE_ADDR_ERROR
else:
Grey_log.error('Error Code: 0x{:02X}'.format(CRC_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return CRC_ERROR
else:
Grey_log.error('Error Code: 0x{:02X}'.format(RECEIVE_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return RECEIVE_ERROR
else:
Grey_log.error('Error Code: 0x{:02X}'.format(SEND_ERROR))
Grey_log.error('-------------------------------------------------------------------------')
return SEND_ERROR
无相关的库文件,有参考脚本可以实现