php实现modbus
PHP 实现 Modbus 通信
Modbus 是一种工业通信协议,常用于设备间的数据交换。PHP 可以通过 TCP/IP 或串口(RTU)与 Modbus 设备通信。以下是两种常见的实现方式:
使用 PHP-Modbus 库
PHP-Modbus 是一个开源的 PHP 库,支持 Modbus TCP 和 RTU。安装方式如下:
composer require adduc/phpmodbus
示例代码(Modbus TCP):
require_once 'vendor/autoload.php';
use ModbusTcpClient\Network\BinaryStreamConnection;
use ModbusTcpClient\Packet\ModbusFunction\ReadHoldingRegistersRequest;
use ModbusTcpClient\Packet\ModbusFunction\ReadHoldingRegistersResponse;
$connection = BinaryStreamConnection::getBuilder()
->setPort(502)
->setHost('192.168.1.1')
->build();
$request = new ReadHoldingRegistersRequest(1, 0, 2);
$response = $connection->connect()->sendAndReceive($request);
if ($response instanceof ReadHoldingRegistersResponse) {
$data = $response->getData();
print_r($data);
}
$connection->close();
使用 socket 直接通信
如果不使用库,可以通过 PHP 的 socket 函数直接与 Modbus TCP 设备通信。
示例代码:
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, '192.168.1.1', 502);
// 构建 Modbus TCP 请求(读取保持寄存器)
$transactionId = 0x0001;
$protocolId = 0x0000;
$length = 0x0006;
$unitId = 0x01;
$functionCode = 0x03;
$startAddress = 0x0000;
$quantity = 0x0002;
$request = pack('nnnnnCCnn', $transactionId, $protocolId, $length, $unitId, $functionCode, $startAddress, $quantity);
socket_write($socket, $request);
$response = socket_read($socket, 1024);
$data = unpack('C*', $response);
print_r($data);
socket_close($socket);
串口通信(Modbus RTU)
对于串口通信,可以使用 php_serial 类或 dio 扩展。
示例代码(使用 dio):
$serial = dio_open('/dev/ttyUSB0', O_RDWR | O_NOCTTY | O_NONBLOCK);
dio_tcsetattr($serial, [
'baud' => 9600,
'bits' => 8,
'stop' => 1,
'parity' => 0
]);
// 构建 Modbus RTU 请求(读取保持寄存器)
$unitId = 0x01;
$functionCode = 0x03;
$startAddress = 0x0000;
$quantity = 0x0002;
$request = pack('CCnn', $unitId, $functionCode, $startAddress, $quantity);
$crc = crc16($request);
$request .= pack('v', $crc);
dio_write($serial, $request);
$response = dio_read($serial, 1024);
function crc16($data) {
$crc = 0xFFFF;
for ($i = 0; $i < strlen($data); $i++) {
$crc ^= ord($data[$i]);
for ($j = 0; $j < 8; $j++) {
if ($crc & 0x0001) {
$crc = ($crc >> 1) ^ 0xA001;
} else {
$crc >>= 1;
}
}
}
return $crc;
}
注意事项
- Modbus TCP 默认端口为 502,需确保防火墙允许通信。
- Modbus RTU 需配置正确的串口参数(波特率、数据位等)。
- 处理二进制数据时需注意字节序(大端或小端)。
- 错误处理需检查 Modbus 异常响应(功能码 + 0x80)。







