【PHP】PHP实现与硬件串口交互,接收硬件发送的实时数据

一、前言

目的:借助虚拟串口软件(VSPD)模拟硬件串口发送数据,使用PHP语言实现接收硬件发送的数据。

我这里的需求是连接天平,把天平的称量数据实时的传送到PHP使用。

使用工具:vspd+串口调试工具

使用语言:PHP

二、效果图

三、准备

1、虚拟串口软件

使用到的工具有VSPD和串口调试工具,其中VSPD是模拟硬件串口,串口调试工具是模拟硬件发送数据,两者配合使用,工具已打包,可直接下载使用:vspd+串口调试工具

2、安装PHP扩展

下载并安装dio扩展,下载地址PECL :: Package :: dio 0.2.0 for Windows,注意要与使用的PHP版本保持一致,下载后将php_dio.dll文件拷贝到/Extensions/php/php7.0.9nts/ext/目录下,再打开php.ini,删除掉"extension=dio"前面的分号,如果没有则直接添加即可,最后重启Apache

四、VSPD和串口调试工具使用

1、VSPD

VSPD可通过上面链接下载,下载解压后,直接运行vspd.exe按提示安装即可。

安装成功后在右侧添加端口,注意端口是成对添加或删除的,两个端口可以互相收发数据。端口添加成功后,打开电脑"设备管理器"中的端口,就可以看到新添加的两个端口。

2、串口调试工具

无需安装,直接运行文件夹里的exe文件即可,在左侧设置好参数,串口号、波特率、数据位、停止位等,这些一般由设备供应商提供。最后点击"打开串口"按钮。

3、测试串口是否可以互相收发数据

再打开一次串口调试工具,选择串口COM4(注意必须是再VSPD里添加的串口组对之间才能互相通信,互相发送、接收数据),设置波特率等参数与COM3一致,在右侧下面的发送数据区输入数据,点击发送,则在COM3端口就会收到发送的数据,同样在COM3的发送数据区输入数据,则在COM4的接收数据区也可以接收到数据,两个是互相的。

如果能互相收发数据,表示两个端口是正常的。

五、PHP实时接收COM串口的数据

后端实现逻辑

1、使用php_dio扩展读取串口传送来的数据

2、设置参数:com4、baud、data、stop,参数要与上传串口调试工具上的参数一致

3、开始连接串口,并循环读取数据,以获得实时变化的数据

4、关闭串口

5、下面代码较为简单,要考虑更多会出现错误的情况,比如说com端口连接失败的情况,读取数据为空时的情况等

5、apiResponse()是自己写的一个返回json格式的函数

前端实现逻辑

1、使用定时器,轮询请求结接口,并把返回的数据实时的更新到input上

2、定义全局变量change用来标识新请求回来的数据是否和上次一致,即串口传送的数据是否发生变化

3、定义全局变量flag用来标识数据未发生变化时,请求的次数

4、其实第一步已经实时获取到了串口发送的数据,如果没有特殊的后续操作第2和3步可以不用。因为我这里的需求是接收天平的实时数据,当天平数据稳定时(说明天平上没有再添加重量),所以加了这两步用来触发其他事件,比如说如果连续5次请求数据都没有发送变化,即flag=5时,此时就可以判定天平上的重量没有发生变化,就可以进行后续操作了。

PHP代码

php 复制代码
/*
 *前端显示页面 
 */
public function index(){
	return $this->fetch();
}

/**
 * 读取天平数据  前端通过ajax请求以获取实时数据
 */
public function getCom(){
	
	//定义com口 接收端口 COM3发送则COM4位接收,反之亦然,baud 波特率 data 数据位 stop 停止位  由供应商提供
	$com='COM4'; $baud = '9600'; $data='8';  $stop = '1';

	set_time_limit(0);

	exec('mode '.$com.': baud='.$baud.' data='.$data.' stop='.$stop.' parity=n xon=on',$output);
	//打开串口  O_RDWR读写模式 O_RDONLY只读
	$ck = dio_open($com . ':', O_RDWR);

	//如果打开串口失败,停止脚本,并输出"打开串口COM3失败"
	if(!$ck){
			
		return apiResponse('110',"打开串口" . $com . "失败");
	}

	//读取串口数据
	//读取长度
	$len = 80;
	//当数据为空时
	do{
		// 读取串口数据并将读取到的数据赋给变量$shuju
		$shuju = dio_read($ck,$len);
	}
	while($shuju == null);

	// 获取浮点值,并反转  如果传过来的数据为83.100,我们需要的正确的数据是1.38
	// $shuju = floatval(strrev($shuju));

	// 关闭串口
	dio_close($ck);
	//读取发送串口的数据
	return apiResponse('200','success',$shuju);

}

前端代码

html 复制代码
<html>
<head>
	<title>实施接收COM串口数据</title>
	<script type="text/javascript" src="/static/index/js/jquery-1.11.3.min.js" ></script>
	<script type="text/javascript" src="/static/index/layui/layui.js"></script>
	<link rel="stylesheet" type="text/css" href="/static/index/layui/css/layui.css">
</head>
<body>
	<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;">
	  <legend>实施接收COM串口数据</legend>
	</fieldset>
	 
	<form class="layui-form layui-form-pane" action="" style="width:60%; margin: 0 auto;">
	  
	  	<div class="layui-form-item" >
		    <div class="layui-block" >
		      	<label class="layui-form-label">COM数据</label>
		      	<div class="layui-input-block" >
		        	<input type="text" name="data"  autocomplete="off" class="layui-input" value="">
		      	</div>
		    </div>
	  	</div>

		<div class="layui-form-item"  style=" padding: 10px; background-color: #F2F2F2; " >
		  	<div class='layui-card'>
			    <div class='layui-card-header' style="font-size: 18px">与上一次是否发送变化</div>
			    <div class='layui-card-body' id="result" style="font-size: 16px">
				    
			    </div>
		  	</div>
		</div> 

	</form>

</body>

<script>


layui.use(['form','element'], function(){
  var form = layui.form
  ,$ = layui.jquery
  ,element = layui.element;

 // setTimeout(getCom, 1000);
  $(document).ready(function(){
		c = setInterval(getCom,1500);   //每1.5秒执行一次
  });

  // 记录数据是否发生变化
  var change = '0';
  // 记录未发生变化次数
  var flag = 0;

  function getCom() {

	  $.ajax({
	  	url:'getCom',
	  	type:'GET',
	  	dataType:'JSON',
	  	success:function (res) {
	  		console.log(res)
	  		if (res.code == '200') {

	  			$('#result').empty();
	  			var html = ''

	  			$("input[name='data']").val(res.data)

	  			if (change == res.data) {
	  				// 未发生变化
	  				flag++
	  				html = '<span style="color:green">未发生变化:'+flag+'</span>'
	  			}else{
	  				// 发生了变化
	  				flag = 0  //数据发生变化后重置变化次数
		  			change = res.data
	  				html = '<span style="color:red">发生了变化</span>'
	  			}
	  			$('#result').append(html)
	  		}else{
	  			layer.msg(res.data)
	  		}
	  	}
	  })
  }
})

</script>
</html>
相关推荐
BingoGo2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo3 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack3 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack4 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo4 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack5 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理6 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082856 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe6 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5