使用phpmodbus连接Modbus/TCP遇地址上限126无法读取32969-34597地址问题
PHP使用phpmodbus读取高地址Modbus/TCP寄存器方案
问题原因
你遇到的126地址限制实际是phpmodbus库的默认校验规则限制了单次读取寄存器的最大数量为126个,而非不支持高地址段,32969~34597的地址范围属于标准16位Modbus寄存器寻址范围,只需调整配置即可正常读取。
解决步骤
1. 先确认地址偏移规则
Modbus TCP协议中保持寄存器的偏移地址是物理地址减1,如果你要读取的32969~34597是设备标注的物理寄存器地址,传入方法前需要先减1得到协议要求的偏移值。
2. 解除库的数量限制(可选)
打开ModbusMaster.php文件,找到readMultipleRegisters方法中的如下校验代码:
if (!($quantity > 0 && $quantity <= 126)) { throw new Exception("Invalid quantity of registers, 1-126 allowed.", 3); }
将126修改为你需要的最大读取数量即可,注意Modbus协议单次请求最大支持读取125个保持寄存器,超过该数量建议分批读取避免设备不兼容。
3. 分批读取实现代码(无需修改库文件,兼容性更好)
如果不想修改第三方库代码,可以用分批读取的方式实现,示例代码如下:
<?php require_once dirname(__FILE__) . '/../Phpmodbus/ModbusMaster.php'; $IP = $_POST["IP"] ; // 物理地址范围转换为偏移地址 $start_physical = intval($_POST["RAM_location"]); $RAM_NUM = intval($_POST["RAM_NUM"]) ; $RAM_location = $start_physical - 1; // 转换为Modbus偏移地址 $modbus = new ModbusMaster($IP, "TCP"); $recData = []; $single_max = 125; // 协议允许单次最大读取数量 $read_times = ceil($RAM_NUM / $single_max); try { // 分批读取 for ($i = 0; $i < $read_times; $i++) { $current_offset = $RAM_location + $i * $single_max; $current_num = min($single_max, $RAM_NUM - $i * $single_max); $temp_data = $modbus->readMultipleRegisters(0, $current_offset, $current_num); $recData = array_merge($recData, $temp_data); } } catch (Exception $e) { echo $modbus; echo $e; exit; } $DataCount = count($recData); $new_redata = array(); $j = $start_physical; for($i = 0;$i < $DataCount;$i = $i+2){ $reI = $recData[$i] * 256; $new_redata[$j] = $reI + $recData[$i+1] ; $j++; } // 输出结果可自行处理 print_r($new_redata); ?>
注意事项
- 读取前确认设备的Slave ID是否为0,大部分设备默认Slave ID为1,如果读取失败可以尝试修改
readMultipleRegisters的第一个参数为1 - 网络不稳定时可以给
ModbusMaster实例设置超时时间,避免请求卡住:$modbus->timeout_sec = 2;
内容的提问来源于stack exchange,提问作者jacklee
相关产品推荐
相关产品推荐

