目录
一、前言
使用PHP语言与硬件设备通信交互,并向COM串口发送和接收数据。
前面写了三篇关于PHP与RS235和USB端口通信的文章,可以作为参考,本文介绍PHP怎么使用RS485串口的Modbus-Rut协议与硬件通信。
【PHP】PHP通过串口与硬件通讯,向硬件设备发送数据并接收硬件返回的数据_php串口通信-CSDN博客
【PHP】PHP实现与硬件串口交互,接收硬件发送的实时数据(上)_php 怎么进行串口通讯-CSDN博客
【PHP】PHP实现与硬件串口交互,向硬件设备发送指令数据(下)_c语言esp32,php怎么发送硬件信息-CSDN博客
二、开发前说明
需求:PHP通过COM串口与天平通信,PHP能够向天平发送指令,并接收天平返回的响应信息。
硬件设备:天平。
串口:RS485。
串口传输协议:Modbus-Rut。
指令集:由天平供应商提供。
开发语言:PHP7.4.3。
框架:ThinkPHP5。
三、效果图
四、安装PHP扩展
下载并安装dio扩展,下载地址PECL :: Package :: dio,注意要与使用的PHP版本保持一致,下载后将php_dio.dll文件拷贝到/Extensions/php/php7.4.3nts/ext/目录下,再打开php.ini,删除掉"extension=dio"前面的分号,如果没有则直接添加即可,最后重启Apache
五、安装phpModbus类库
使用composer安装modbus,注意安装前提是PHP ≥ 7.4.0,dio ≥ 0.2.0
由于modbus协议支持TCP/UDP和RTU两种,由于本项目使用的是COM串口,所以使用的是RTU协议,所以需要安装支持Modbus RTUd 类库
bash
composer require fawno/modbus
安装完成之后,会在vendor文件夹里生成fawno/modubs文件夹,表示安装成功。
六、通信逻辑
dio扩展和modbus类库安装完成后,通信的前提就完成了。
由于Modbus RTU协议发送和接收的是十六进制的数据,所以可以根据自己需要对发送和接收的数据进行转码,转成十进制,方便使用。
业务逻辑
① 引用modbus类库
② 实例化
③ 打开COM串口
④ 发送指令
⑤ 接收响应结果
⑥ 对返回的结果进行解析,解析成需要的格式
⑦ 关闭串口
七、完整实例
- 我这里发送的指令是"01 03 00 00 00 02 C4 0B",使用chr()函数转成十六进制
- 延迟100ms接收响应
- 将返回的结果转换成十六进制格式
- 对返回的结果进行解析,解析成需要的格式,我这里需要的是重量(浮点数)
php
<?php
namespace app\home\controller;
use think\Controller;
use think\Db;
use Fawno\PhpSerial\Config\BaudRates;
use Fawno\PhpSerial\Config\StopBits;
use Fawno\PhpSerial\Config\Parity;
use Fawno\PhpSerial\Config\DataBits;
use Fawno\PhpSerial\SerialConfig;
use Fawno\PhpSerial\SerialDio;
use Fawno\Modbus\ModbusDDS238;
use Fawno\Modbus\ModbusRTU;
class Tianpingapi extends Controller
{
public function putCommond()
{
set_time_limit(0);
$ret = []; // 返回数组
$response = '初始化';
include "../vendor/fawno/modbus/autoload.php";
$com='COM4'; $baud = '9600'; $data='8'; $stop = '1';
try {
// 指令 获取当前重量
// $commond = "01 03 00 00 00 02 C4 0B";
$commond = chr(0x01) . chr(0x03) . chr(0x00) . chr(0x00) . chr(0x00) . chr(0x02) . chr(0xC4) . chr(0x0B);
$dds238 = new ModbusDDS238($com);
$dds = $dds238->open();
if ($dds) {
TLog("打开串口:".$com."成功");
}else{
TLog("打开串口:".$com."失败");
TLog(">>>> end <<<<");
TLog("\r\n");
}
// 读取串口数据
TLog(">>>> 天平模块 <<<<");
TLog(">>>> start <<<<");
// 延迟100ms
usleep(100000);
// 发送指令
$dds->send($commond);
// 接收设备的响应
$response = $dds238->read();
if (!empty($response)) {
// 转成十六进制,并且字母小写
$hex = strtolower(bin2hex($response));
TLog("读取串口".$com."的响应结果成功:十六进制【".$hex."】");
// 响应结果处理,返回重量
$wei = $this->responseParse($hex);
$log = "接收:".$hex."。重量:".$wei. "\r\n";
// 响应结果解析成功
TLog($log);
$ret['code'] = '200';
$ret['data'] = $wei;
}else{
TLog("读取串口".$com."的响应结果失败"."\r\n");
$ret['code'] = '110';
$ret['data'] = 99999;
}
TLog(">>>> end <<<<");
TLog("\r\n"."-------------------------------------");
// 关闭串口
$dds238->close();
} catch (Exception $e) {
$ret['code'] = '110';
$ret['message'] = $e->getMessage();
}
return $ret;
}
}