php对接Modbus rtu串口设备并对设备参数读写详细讲解

1、下载PhpSerial.php类库

https://github.com/Xowap/PHP-Serial/tree/develop

2、案例demo

<?php
require_once 'PhpSerial.php'; // 确保路径正确

$serial = new PhpSerial;

// 设置设备,例如 COM1 在Windows上,/dev/ttyS0 在Linux上
$serial->deviceSet("/dev/ttyS0"); // 或者在Windows上使用 "COM1"
$serial->confBaudRate(9600);      // 设置波特率
$serial->confParity("none");      // 设置校验位
$serial->confCharacterLength(8);  // 设置数据位
$serial->confStopBits(1);         // 设置停止位
$serial->confFlowControl("none"); // 设置流控

try {
    $serial->deviceOpen('w+');  //打开端口
} catch (Exception $e) {
    echo "串口连接打开失败: " . $e->getMessage();
    exit;
}

//CRC验证方法
function calculateCrc($data) {
        $crc = 0xFFFF;
        foreach (str_split($data, 2) as $byte) {
                $crc ^= hexdec($byte);
                for ($i = 0; $i < 8; $i++) {
                        if ($crc & 0x0001) {
                                $crc = ($crc >> 1) ^ 0xA001;
                        } else {
                                $crc >>= 1;
                        }
                }
        }
        return sprintf('%04X', $crc);
}
//拼接成modbus rtu 16进制请求字符串
$deviceAddress = '01'; //从地址
$functionCode = '03';   //功能码
$startAddress = '0000'; //起始寄存器地址
$registerCount = '0002'; //读取几位
$request = $deviceAddress . $functionCode . $startAddress . $registerCount;
$crc = calculateCrc($request);
//拼接CRC验证,最后四位是CRC验证参数
$fullRequest = $request . substr($crc, 2, 2) . substr($crc, 0, 2); // 调整字节顺序
$serial->sendMessage(hex2bin($fullRequest)); // 发送二进制请求四、接收并解析响应数据
//加个1/2秒延迟,不加延迟可能有时返回空
usleep(500000);
$response = $serial->readPort(); // 读取串口数据 if (!empty($response)) { $hexResponse = bin2hex($response); // 转换为十六进制字符串 $deviceAddr = substr($hexResponse, 0, 2); //从地址 $functionCode = substr($hexResponse, 2, 2); //功能码 $byteCount = substr($hexResponse, 4, 2); //返回的参数长度,每个长度占两位,如04则是,0000 0000 $registerValues = str_split(substr($hexResponse, 6, hexdec($byteCount)*2), 4); // 每4字符为一个寄存器,返回寄存器值数组 // 验证CRC(需重新计算接收数据的CRC) $receivedCrc = substr($hexResponse, -4); $calculatedCrc = calculateCrc(substr($hexResponse, 0, -4)); // if ($receivedCrc === $calculatedCrc) { echo "寄存器值: " . implode(', ', array_map('hexdec', $registerValues)); // } else { // echo "CRC校验失败"; // } } //关闭串口 $serial->deviceClose();

modbus RTU十六进制字符串拼接

企业微信截图_17684481145737

 RTU字符串解析

请求的RTU字符串
  01    03         0000        0002                  C40B
从地址  功能码     起始寄存器     读取寄存器参数数量      CRC验证(对前部分的字符串CRC加密得来)

返回的RTU字符串
  01    03               04                                            0000              0002        FB8B
从地址  功能码     返回的参数长度(02代表1个参数,04代表2个,06代表3个)        返回参数1(16进制)     参数2      CRC验证(对前部分的字符串CRC加密得来)
    

 

企业微信截图_17684482705698

 

posted on 2026-01-15 11:49  泽一年  阅读(1)  评论(0)    收藏  举报

导航