【PHP】PHP通过串口与硬件通讯,向硬件设备发送数据并接收硬件返回的数据

news2025/1/22 12:56:09

一、前言

之前写过两篇PHP实现与硬件串口交互的文章,一篇是【PHP】PHP实现与硬件串口交互,接收硬件发送的实时数据(上)_php串口通信-CSDN博客,另一篇是【PHP】PHP实现与硬件串口交互,向硬件设备发送指令数据(下)-CSDN博客。上篇是介绍怎样通过RS232接口接收硬件发送的数据,下篇是介绍通过USB转RS232线怎样向硬件设备发送数据。

本篇把两个功能综合一起介绍,成为一个完整的功能。

二、开发前说明

需求:PHP通过串口与天平通信,PHP能够向天平发送指令,并接收天平返回的响应信息。

硬件设备:天平。

传输线:USB转RS232接口,USB插到电脑上,RS232接到天平单片机上。

指令集:由天平供应商提供。

开发语言:PHP。

业务逻辑是:PHP先向硬件设备发送指令,硬件设备接收到指令后,返回响应结果,PHP再去接收返回的响应结果,进行后续业务处理。

三、效果图

四、代码

后端代码说明:

1、接收前端穿过来的指令,根据天平供应商给的文档拼接要发送的数据格式,这里是以“\r\n”为结束符,同时返回的数据也带有"\r\n",所以需要对接收的数据进行处理后才能使用;

2、定义串口、波特率、数据位、停止位等参数,这样按照硬件开发文档填写;

3、打开串口,并向串口发送指令;

4、发送成功后,等待0.5s,再去接收设备返回的数据,因为软件发送数据给硬件,硬件再接收处理,返回响应数据,中间需要点时间,如果不设置等待时间而是直接读取,是没有数据的,因为硬件还没来得及返回;

5、关闭串口连接;

6、其中“TLog()”方法是我用来记录整个执行流程调试使用的,就是往txt写下执行内容。

PHP代码

/**
 * 发送数据 页面
 */
public function put()
{

	$list = array(
		array("num" => "1", "gongneng" => "测试", "commond" => "AT"),
		array("num" => "3", "gongneng" => "清零", "commond" => "AT+ZERO"),
		array("num" => "4", "gongneng" => "获取重量", "commond" => "AT+WEI"),
		array("num" => "5", "gongneng" => "设置获取重量方式", "commond" => "AT+AUTO=X"),
		array("num" => "6", "gongneng" => "查看当前重量获取方式", "commond" => "AT+AUTO?"),
		array("num" => "7", "gongneng" => "设置开机清零方式", "commond" => "AT+OPENC=X"),
		array("num" => "8", "gongneng" => "查看当前开机清零方式", "commond" => "AT+OPENC?"),
		array("num" => "9", "gongneng" => "校准及校准参数", "commond" => "AT+CAL=X"),
		array("num" => "10", "gongneng" => "发送校准砝码指令", "commond" => "AT+CALW"),
		array("num" => "11", "gongneng" => "校准参数查询", "commond" => "AT+CAL?"),
		array("num" => "12", "gongneng" => "切换重量输出格式", "commond" => "AT+PRINTX=X"),
		array("num" => "13", "gongneng" => "查看当前输出格式", "commond" => "AT+PRINTX?")
	);

	$this->assign(['list'=>$list]);
	return $this->fetch();
}

/**
 * 发送指令
 * com9接收端
 */
public function putCom(){

	if (request()->isPost()) {

		set_time_limit(0);

		// 接收指令 原指令
		$commond = trim(input('post.commond'));
		// $commond = "AT";	

		if (!empty($commond)) {

			// 要发送的指令
			$commond_send = $commond."\r\n";

			TLog(">>>> start <<<<");
			TLog('输入指令:'.$commond);	

			//定义com接收端口  baud 波特率 data 数据位 stop 停止位  由供应商提供
			$com='COM9'; $baud = '9600'; $data='8';  $stop = '1'; $output = array();

			exec('mode '.$com.': baud='.$baud.' data='.$data.' stop='.$stop.' parity=n xon=on',$output);

			//打开串口  O_RDWR读写模式 O_RDONLY只读
			$ck = @fopen($com, 'w+');

			TLog("准备打开串口" . $com);

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

			TLog("打开串口" . $com . "成功");

			TLog("准备向串口".$com."发送指令:【" . $commond."】");

			//向串口发送数据;
		  	$rs = fwrite($ck, $commond_send);

			if ($rs) {
		
				TLog("向串口".$com."发送指令发送成功:【" . $commond."】");

				// 等待0.5秒
			  	usleep(500000);

				// 接收设备的响应  
				$response = fread($ck, 128);

				TLog("准备读取串口".$com."的响应结果");
				if ($response) {

					// 过滤掉返回结果中的\r\n
					$response =  str_replace(array("\r", "\n"), '', $response);
					TLog("读取串口".$com."的响应结果成功:【".$response."】");

				}else{

					TLog("读取串口".$com."的响应结果失败");
				}

			}else{
				TLog("向串口".$com."发送指令发送失败:【" . $commond."】");

				return apiResponse('110',"向串口".$com."发送指令发送失败:【" . $commond."】");
			}

			TLog(">>>> end <<<<");
			TLog("\r\n");
			//关闭端口    
	  		fclose($ck);
			
			return apiResponse('200','success',$response);
		}else{
			return apiResponse('110','指令不能为空');
		}
	}else{
		return apiResponse('110','非法请求');
	}
	
}

前端代码

<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>
	 
	<div class="layui-row" style="width:60%; margin: 0 auto;">
		<form class="layui-form layui-form-pane" action="">
		  	<div class="layui-form-item" >
			    <div class="layui-inline" >
			      	<label class="layui-form-label">发送指令</label>
			      	<div class="layui-input-inline" style="width: 500px;">
			        	<input type="text" name="commond"  autocomplete="off" class="layui-input" value="AT">
			      	</div>
			    </div>
			    <div class="layui-inline">
			      <button type="submit" class="layui-btn layui-btn-normal" lay-submit="" lay-filter="demo1">提交指令</button>
			      <button type="reset" class="layui-btn layui-btn-primary">重置</button>
			    </div>
		  	</div>
		</form>
	</div>

	<div class="layui-row layui-col-space10" style="width:60%; margin: 0 auto;">
		<div class="layui-col-md4">
			<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> 
		</div>

		<div class="layui-col-md8">
			<table class="layui-table">
			  <colgroup>
			    <col width="20%">
			    <col width="40%">
			    <col width="40%">
			  </colgroup>
			  <thead>
			    <tr>
			      <th>序号</th>
			      <th>功能</th>
			      <th>指令</th>
			    </tr> 
			  </thead>
			  <tbody>
			  	{volist name="list" id="vo"}
			    <tr>
			      <td>{$vo.num}</td>
			      <td>{$vo.gongneng}</td>
			      <td>{$vo.commond}</td>
			    </tr>
			    {/volist}
			  </tbody>
			</table>
		</div>
	</div>
</body>

<script>

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

  // 提交
  form.on('submit(demo1)', function(data){
    
    var commond = $("input[name='commond']").val()
	  $.ajax({
	  	url:'putCom',
	  	type:'POST',
	  	dataType:'JSON',
	  	data:{commond:commond},
	  	success:function (res) {
	  		console.log(res)
	  		if (res.code == '200') {
	  			layer.msg(res.message)

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

  				html = '<div>输入指令:'+commond+'</div><div style="color:green">返回内容:'+res.data+'</div>'
	  			$('#result').append(html)
	  		}else{
	  			layer.msg(res.message)
	  		}
	  	}
	  })
	  return false
  });
})

</script>
</html>

  两篇PHP实现与硬件串口交互的文章,【PHP】PHP实现与硬件串口交互,接收硬件发送的实时数据(上)_php串口通信-CSDN博客,【PHP】PHP实现与硬件串口交互,向硬件设备发送指令数据(下)-CSDN博客。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1495651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3+Vue Router使用<transition>过渡动画实现左右分栏后台布局

摘要 利用Vue3及其配套的Vue Router实现后台管理系统中的页面过渡动画。文章首先简要介绍了Vue3的特性和Vue Router的基本用法&#xff0c;利用Vue3提供的组件以及Vue Router的路由钩子函数来实现页面过渡效果。 代码结构 在 components 里有4个组件&#xff0c;其中 Layout…

HTTPS是什么,那些行业适合部署呢?

随着在线活动的增加&#xff0c;对您共享的关键数据的威胁已经产生了严重的后果&#xff0c;包括欺诈性金融交易、在线身份盗窃等。此外&#xff0c;随着技术使用的增加&#xff0c;网络攻击也变得更加复杂和具有挑战性。 毫无疑问&#xff0c;互联网用户的数据安全意识成倍增长…

(学习日记)2024.03.06:UCOSIII第八节:空闲任务+阻塞延时+main函数修改

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

uniapp小程序获取位置权限(不允许拒绝)

需求 小程序上如果需要一些定位功能&#xff0c;那么我们需要提前获取定位权限。我们页面的所有功能后续都需要在用户同意的前提下进行&#xff0c;所以一旦用户点了拒绝&#xff0c;我们应该给予提示&#xff0c;并让用于修改为允许。 实现 1.打开手机GPS 经过测试发现即使…

第102讲:MySQL多实例与Mycat分布式读写分离的架构实践

文章目录 1.Mycat读写分离分布式架构规划2.在两台服务器中搭建八个MySQL实例2.1.安装MySQL软件2.2.创建每个MySQL实例的数据目录并初始化2.3.准备每个实例的配置文件2.4.准备每个实例的启动脚本2.6启动每台机器的MySQL多实例2.7.为每个MySQL实例设置密码2.8.查看每个MySQL实例的…

2024三掌柜赠书活动第十三期:API安全技术与实战

目录 前言 API安全威胁与漏洞 API安全技术与实践 API安全实战案例 关于《API安全技术与实战》 编辑推荐 内容简介 作者简介 图书目录 书中前言/序言 《API安全技术与实战》全书速览 结束语 前言 随着互联网的快速发展和应用程序的广泛使用&#xff0c;API&#xff…

excel统计分析——正交设计

参考资料&#xff1a;生物统计学 单因素试验通常采用完全随机设计活动随机区组设计&#xff1b;两因素试验通常采用析因设计&#xff1b;多因素试验不考虑因素间的互作时&#xff0c;可以采用拉丁方设计或正交拉丁方设计&#xff1b;需要考虑因素间的互作时&#xff0c;析因设计…

手回科技:人生的“小雨伞”,能否撑起自己的增长路?

有道是一年之计在于春。新年伊始&#xff0c;多家券商发布研报表达了对2024年保险市场表现的观点。 比如&#xff0c;开源证券表示&#xff0c;政策组合拳带来beta催化&#xff0c;保险业务端和弹性占优&#xff1b;中国银行证券指出&#xff0c;2024年&#xff0c;保险行业景…

HarmonyOS应用开发-使用Local Emulator运行应用/服务(使用本地模拟器)

1、单击File > Settings > SDK&#xff0c;下拉框选择HarmonyOS&#xff0c;勾选并下载Platforms下的System-image和Tools下的Emulator资源。 点击ok&#xff0c;等待安装完成 2、单击菜单栏的Tools > Device Manager&#xff0c;在Local Emulator页签&#xff0c;…

百度给程序员发放京东购物卡,注册即送30元购物卡

活动真实有效&#xff1a; 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09;https://comate.baidu.com/?inviteCodeexf818mt 活动参与流程说明&#xff1a;点击下面的邀请链接进行登陆&#xff0c;注意一定要邀请链接&#xff0c;因为通过链接注册可以获…

300分钟吃透分布式缓存-20讲:Redis如何处理文件事件和时间事件?

Redis 事件驱动模型 事件驱动模型 Redis 是一个事件驱动程序&#xff0c;但和 Memcached 不同的是&#xff0c;Redis 并没有采用 libevent 或 libev 这些开源库&#xff0c;而是直接开发了一个新的事件循环组件。Redis 作者给出的理由是&#xff0c;尽量减少外部依赖&#xff…

【Java】关于ZooKeeper的原理以及一致性问题,协议和算法和ZooKeeper的理论知识和应用 场景

1. 目录 目录 1. 目录 2. 什么是ZooKeeper 3. 一致性问题 4. 一致性协议和算法 4.1. 2PC&#xff08;两阶段提交&#xff09; 4.2. 3PC&#xff08;三阶段提交&#xff09; 4.3. Paxos 算法 4.3.1. prepare 阶段 4.3.2. accept 阶段 4.3.3. paxos 算法的死循环…

2024年阿里云2核4G服务器租用价格_2核4G性能测评_支持人数

阿里云2核4G服务器多少钱一年&#xff1f;2核4G配置1个月多少钱&#xff1f;2核4G服务器30元3个月、轻量应用服务器2核4G4M带宽165元一年、企业用户2核4G5M带宽199元一年。可以在阿里云CLUB中心查看 aliyun.club 当前最新2核4G服务器精准报价、优惠券和活动信息。 阿里云官方2…

JavaScript 入门手册(一)

目录 一、JavaScript 是什么? 1.1 JavaScript 介绍 1.2 JavaScript 与 ECMAScript 的关系 1.3 JavaScript 是脚本语言 1.4 JavaScript 的特点 1.5 运行 JavaScript 1.6 保留关键字 二、Node.js 是什么&#xff1f; 2.1 运行时是什么&#xff1f; 2.2 Node.js 的组成…

Ubuntu20.04安装并配置vscode

Ubuntu20.04安装并配置vscode vscode安装miniconda安装创建虚拟python3.8环境pytorch和匹配的cuda安装 vscode安装 VSCode可以通过 Snapcraft 商店或者微软源仓库中的一个 deb 软件包来安装。 我们这里选用安装VSCode snap版&#xff0c;打开你的终端(CtrlAltT)并且运行下面的…

LeetCode_25_困难_K个一组翻转链表

文章目录 1. 题目2. 思路及代码实现&#xff08;Python&#xff09;2.1 模拟 1. 题目 给你链表的头节点 h e a d head head &#xff0c;每 k k k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k k k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节…

VTK的编译和部署,配合c++和visual studio2022,VTK开发环境的配置

1.下载 在官网选择最新的版本 Download | VTK 下载之后进行解压&#xff0c;然后再里面创建build目录&#xff0c;方便后面使用cmake进行编译 2.对源码进行编译 打卡Cmake&#xff0c;如图操作 可以看到点击configure之后&#xff0c;cmake对我们的代码在进行处理 处理完成之…

openssl3.2 - exp - 产生随机数

文章目录 openssl3.2 - exp - 产生随机数概述笔记END openssl3.2 - exp - 产生随机数 概述 要用到openssl产生的随机数, 查了资料. 如果用命令行产生随机数, 如下: openssl rand -hex -num 6 48bfd3a64f54单步跟进去, 看到主要就是调用了一个RAND_bytes(), 没其他了. 官方说…

【vue.js】文档解读【day 2】 | 计算属性

如果阅读有疑问的话&#xff0c;欢迎评论或私信&#xff01;&#xff01; 本人会很热心的阐述自己的想法&#xff01;谢谢&#xff01;&#xff01;&#xff01; 文章目录 计算属性计算属性 vs 方法可计算属性Getter不应有副作用避免直接修改计算属性值 计算属性 我们已经学习…

基于SpringBoot+Vue+ElementUI+Mybatis前后端分离管理系统超详细教程(二)

学习后端CRUD操作 书接上文&#xff0c;我们学习了前后端分离项目的基础环境配置和用户管理模块的前后端基础搭建&#xff0c;以下链接是上一节教程内容详细步骤&#xff0c;友友们可以跟着步骤实操。本节课程我们在前面项目的基础上接着学习后端CRUD操作&#xff0c;真正打通数…