普通用户
关于网络组件客户接收数据后解析的问题 [复制链接]
sunriseshu 发表于 2026-04-29 74 2

通过modbustcp获取三菱FX3U M0-M29寄存器的状态,但是有数据传入就崩溃退出,帮忙看下是哪里的原因:



事件 客户1.收到数据(源对象 为 客户,数据值 为 字节型[])
变量 位号 为 整数型
变量 字节号 为 整数型
变量 字节值 为 整数型
变量 buf 为 字节型[]={0,0,0,0}

' 先取出Modbus返回的4个数据字节
buf[0] = 数据值[9]
buf[1] = 数据值[10]
buf[2] = 数据值[11]
buf[3] = 数据值[12]
变量循环(i = 0,29,1)
字节号 = i / 8
位号 = i % 8
字节值 = 到整数(buf[字节号])
M状态[i] = 假
如果(位号 == 0 且 (字节值%2)>=1)
M状态[i] = 真
否则 如果(位号 == 1 且 (字节值%4)>=2)
M状态[i] = 真
否则 如果(位号 == 2 且 (字节值%8)>=4)
M状态[i] = 真
否则 如果(位号 == 3 且 (字节值%16)>=8)
M状态[i] = 真
否则 如果(位号 == 4 且 (字节值%32)>=16)
M状态[i] = 真
否则 如果(位号 == 5 且 (字节值%64)>=32)
M状态[i] = 真
否则 如果(位号 == 6 且 (字节值%128)>=64)
M状态[i] = 真
否则 如果(位号 == 7 且 (字节值%256)>=128)
M状态[i] = 真
结束 如果
结束循环
结束 事件

官方技术组 2026-04-29

修正版代码:

事件 客户1.收到数据(源对象  客户,数据值  字节型[])
    变量 位号  整数型
    变量 字节号  整数型
    变量 字节值  整数型
    变量 buf  字节型[]={0,0,0,0}
    ' 安全判断,防止数据太短崩溃
    如果 (取字节集长度(数据值) < 11)
        返回
    结束 如果
    ' 正确取4个字节(从第8字节开始)
    buf[0] = 数据值[7]
    buf[1] = 数据值[8]
    buf[2] = 数据值[9]
    buf[3] = 数据值[10]
    ' 循环读取 M0 ~ M29(共30位)
    变量循环(i = 0,29,1)
        字节号 = i / 8
        位号 = i % 8
        字节值 = 到整数(buf[字节号])
        M状态[i] = 
        如果(位号 == 0  (字节值 % 2)>=1)
            M状态[i] = 
        否则 如果(位号 == 1  (字节值 % 4)>=2)
            M状态[i] = 
        否则 如果(位号 == 2  (字节值 % 8)>=4)
            M状态[i] = 
        否则 如果(位号 == 3  (字节值 % 16)>=8)
            M状态[i] = 
        否则 如果(位号 == 4  (字节值 % 32)>=16)
            M状态[i] = 
        否则 如果(位号 == 5  (字节值 % 64)>=32)
            M状态[i] = 
        否则 如果(位号 == 6  (字节值 % 128)>=64)
            M状态[i] = 
        否则 如果(位号 == 7  (字节值 % 256)>=128)
            M状态[i] = 
        结束 如果
    结束循环
结束 事件
回复
官方技术组 2026-04-29

注意:以下答案为轻语言安卓小模型分析并生成,可先尝试根据下面答案修改,如果无效,请参考开发文档:http://doc.vcnstudio.com/android/debug.html 获取APP的崩溃错误原因,然后跟帖回复错误原因。

一、崩溃的核心原因

1. 数组越界(最主要崩溃原因)

你读取 M0~M29,一共 30 个位

需要的字节数 = 30 / 8 = 3.75 → 4字节你写的是:

buf[0] = 数据值[9]
buf[1] = 数据值[10]
buf[2] = 数据值[11]
buf[3] = 数据值[12]

Modbus TCP 响应报文格式不是这样的!

正常 Modbus TCP 读线圈(读 M)响应:

  • 第 7 个字节 = 字节长度
  • 数据从 第 8 个字节开始

你硬写死取 9、10、11、12,一旦返回数据长度不够,直接数组越界崩溃!

2. 位判断逻辑错误、冗余、极易出错

你用 %2、%4、%8... 这种写法完全没必要,而且逻辑不标准,容易算错。

3. 没有判断返回功能码、没有异常处理

设备返回错误码时,你直接取数据,必崩溃


二、完整修复版代码(直接替换即可)

修复点:

  1. 正确解析 Modbus TCP 响应报文
  2. 安全判断长度,防止越界
  3. 标准位运算判断,不崩溃、逻辑清晰
  4. 支持 M0~M29 30 个位
事件 客户1.收到数据(源对象  客户,数据值  字节型[])
    变量 位号  整数型
    变量 字节号  整数型
    变量 字节值  整数型
    变量 数据长度  整数型
    ' 安全判断:防止数据太短直接崩溃
    如果 (取字节集长度(数据值) < 8)
        ' 数据不完整,直接退出,不崩溃
	返回
    结束 如果
    ' Modbus TCP 标准解析:第7字节 = 后续数据长度(读M/线圈返回的字节数)
    数据长度 = 到整数(数据值[6])
    如果 (数据长度 < 4)
        ' 不够4字节,退出        返回     
    结束 如果
    ' 正确取4个字节(从第8字节开始)
    变量 buf  字节型[] = {0,0,0,0}
    buf[0] = 数据值[7]
    buf[1] = 数据值[8]
    buf[2] = 数据值[9]
    buf[3] = 数据值[10]
    ' 循环读取 M0 ~ M29(共30位)
    变量循环(i = 0, 29, 1)
        字节号 =  i / 8      ' 整除
        位号 = i % 8
	字节值 = 到整数(buf[字节号])
	' 标准位判断:1<<位号 = 对应位的掩码
	如果 ((字节值 & (1 << 位号)) != 0)
	    M状态[i] = 
	否则
	    M状态[i] = 
	结束 如果
    结束循环
结束 事件


三、为什么你原来的代码会崩溃?

你写的:

buf[0] = 数据值[9]
buf[1] = 数据值[10]
buf[2] = 数据值[11]
buf[3] = 数据值[12]

如果返回报文只有 10 个字节,你访问 数据值[12] 直接数组越界崩溃


四、测试验证(你可以直接用)

  • M0~M7 → buf[0]
  • M8~M15 → buf[1]
  • M16~M23 → buf[2]
  • M24~M29 → buf [3](只用了前 6 位)

代码完全匹配三菱 FX3U Modbus TCP 地址规则


总结

  1. 崩溃原因 = 数组越界(取错了 Modbus 数据位置)
  2. 修复 = 用我给的完整代码直接替换
  3. 逻辑 = 标准位运算,稳定不崩溃
  4. 支持 M0~M29 30 个位,完美匹配 FX3U
回复
 作者信息
sunriseshu
普通用户 云验证
专业开发指导服务

响应时间:5分钟

服务方式:官方1对1服务

工作时间:工作日 9:00 - 18:30

专业团队 · 开发指导 · 极速响应


官网 | 基础视频教程 | 在线文档 下载 VcnStudio IDE

© VcnStudio Inc All Rights Reserved

蜀ICP备17024229号