[咕咕李大哥的A面]通过MODBUS协议写三菱PLC高低位寄存器导致威纶通触摸屏数值显示不正常的解决办法

您所在的位置:网站首页 三菱plc读取后如何显示数字 [咕咕李大哥的A面]通过MODBUS协议写三菱PLC高低位寄存器导致威纶通触摸屏数值显示不正常的解决办法

[咕咕李大哥的A面]通过MODBUS协议写三菱PLC高低位寄存器导致威纶通触摸屏数值显示不正常的解决办法

2024-07-15 01:23| 来源: 网络整理| 查看: 265

一、三菱32位寄存器说明

        三菱自带数据寄存器(D)为16位,最大可储存16位二进制数:1111 1111 1111 1111,即16进制:FF FF,换算为十进制为65535(无符号),而在日常使用过程中,计数经常需要超过65535,因此需要使用32位寄存器,而三菱PLC的32位寄存器是2个16位寄存器做高低位寄存器合成的。

        在梯形图中,我们可以使用DMOV指令,DMOV指令可以传送32位以内的数。DMOV K10 D0,就是把十进制的10传送到D0和D1中,其中D1存高位,D0存低位,其中D1D0组成就是32位寄存器。

        使用32位数据寄存器,最大可存入十进制数:4294967295(无符号),可满足大部分使用需求。

 二、MODBUS多寄存器写入功能说明

        MODBUS提供多寄存器写入的功能码“10”,请求本文格式见下图:

        当我们需要在1号从机PLC的D10中写入十进制数:131073(16进制0002 0001)时,这个数超过65535,需要占用两个寄存器。

        因此他的请求文本格式为:01 10 00 0A 00 02 04 00 02 00 01,根据上面的功能代码说明,我们分析一下他的结构:

        所以,我们只需要将数字转化为16进制,就能通过MODBUS功能码将数值传输到PLC的数据寄存器中,在实际使用中需要在请求文本的末尾加上CRC16校验码,校验码可以通过网站自动计算,上面的请求文本加上末尾校验码的完整数值为:01 10 00 0A 00 02 04 00 02 00 01 A3 D1,最后的A3 D1就是校验码。

三、多寄存器写入高低位规则差异

        三菱/威纶通的高低位定义:数字大的寄存器为高位,数字小的寄存器为低位。

        MODBUS写多寄存器时的高低位定义:数字小的寄存器为高位,数字大的寄存器为低位。

        因此,使用MODBUS写入的数据高低位与三菱设定的高低位相反,导致PLC识别及威纶通触摸屏数值元件显示错误。

四、解决办法

①使用威纶通宏指令:

使用宏指令,新增以下程序:

macro_command main() short a,b int c,d GetData(a,"Mitsubishi FX0S/FX0N/FX1S/FX1N/FX2/FX3SA",D,11,1) GetData(b,"Mitsubishi FX0S/FX0N/FX1S/FX1N/FX2/FX3SA",D,10,1) c=b*65536 d=c+a SetData(d,"Local HMI",lw,0,1) end macro_command

该指令的功能是将D10和D11的高低位换算合成十进制数存储在触摸屏的LW0寄存器中,再通过威纶通触摸屏的数值元件显示LW0的数值即可正确显示。

也可以直接导入.ebm来新增宏指令,本文使用的文件会上传到云。

使用宏指令修复高低位数据后:

传入数值与显示数值相同,可正常显示32位数值。

②修改请求文本顺序

将上面的请求文本:01 10 00 0A 00 02 04 00 02 00 01,

修改为:01 10 00 0A 00 02 04 00 01 00 02

在请求文本直接替换高低位数据来保证高低位逻辑与PLC逻辑一致,也能使32位寄存器正常工作。

在Python中使用串口模块传输时的解决方式:

raw_data = [1, 16, 10, 2, 4, 131073] # 1(从站号), 16(功能码10H), 10(寄存器D10), 2(寄存器2个), 4(字节数4个), 131073(写入数值) hex_data = [format(x, 'X').zfill(4) for x in raw_data] print("hex1", hex_data) string = hex_data[0] hex_data[0] = string[-2:] # 从站号只需1位 string = hex_data[1] hex_data[1] = string[-2:] # 功能码只需1位 print("hex2", hex_data) try: hex_data[4] # 确认是否为多寄存器写入 except: print("no hex 4") else: string = hex_data[4] hex_data[4] = string[-2:] # 字节数只需1位 print("hex3", hex_data) string = hex_data[5] hex_data[5] = string.zfill(8) # 补齐32位(8位16进制) print("hex4", hex_data) string = hex_data[5] string1 = string[-4:] string2 = string[:4] print("str1", string1, string2) hex_data[5] = ''.join([string1, string2]) # 数值前后四位互换(高低位互换) print("hex5", hex_data) # 将 hex_data 转换为 str_data str_data = ' '.join([x[i:i + 2] for x in hex_data for i in range(0, len(x), 2)]) print("str", str_data) # 将字符串转换为十六进制数组 data_array = [int(x, 16) for x in str_data.split(' ')] print("data0", data_array) string1 = data_array[9] string2 = data_array[10] data_array[9] = data_array[7] data_array[10] = data_array[8] data_array[7] = string1 data_array[8] = string2 print("data", data_array) # 计算CRC校验码 crc = 0xFFFF for i in range(len(data_array)): crc ^= data_array[i] for j in range(8): if crc & 1: crc >>= 1 crc ^= 0xA001 else: crc >>= 1 # 将CRC校验码添加到原始数据后面 crc_code = str_data + ' ' + format(crc & 0xFF, '02X') + ' ' + format((crc >> 8) & 0xFF, '02X') print("crc", crc_code) 五、其他说明

使用威纶通数值元件显示32位数值时,需要使用32-bit unsigned模式

结语

新人发布,欢迎讨论

B站@咕咕李大哥



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3