在 Windows 上使用 PHP 进行串行通信

发布于 2024-07-15 05:15:41 字数 549 浏览 8 评论 0原文

我正在寻找一种在 Windows 上与 RS232 串行 COM 端口进行通信的方法。 我在网上找到了 2 个解决方案,一个 不是完全免费的(引入了故意的延迟)功能)和 另一个,在 Windows 上功能有限。 后者只能写入 Windows 上的 COM 端口,而不能读取。

我无法查看第一个解决方案的代码,因为它被编译成 .dll (这是有道理的,否则人们可以编辑延迟而不购买它......)而第二个解决方案似乎只使用 fopen()打开端口,然后使用 fwrite() 对其进行写入,就像对流所做的那样。 但显然害怕它没有任何回报。

我知道这是可能的,因为第一个解决方案就是这样做的,尽管它确实需要 Apache 使用 php-cgi 模块而不是 php5module。

有任何想法吗?

I am looking for a way to communicate with RS232 serial COM port on windows. I have found 2 solutions on the net, one which is not totally free (introduces deliberate delays on the function) and another with limited capability on Windows. The latter can only write to a COM port on Windows, not read.

I can't look at the code of the first solution since it is compiled into a .dll (makes sense, otherwise people can just edit the delay and not purchase it...) and the second one seems only to use fopen() to open the port and later fwrite() to it for writing, just like one would do to a stream. But apparently freading it returns nothing.

I know it's possible as the first solution did it, although it does require Apache to use php-cgi module instead of php5module.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

云淡月浅 2024-07-22 05:15:42

另一种可能的方法是通过类似 w32api_register_function()ffi 然后使用 串行通信调用以使其在 Windows 下工作。

Another possible way would be to use the Win32 API through something like w32api_register_function() or ffi and then use serial communications calls to get it to work under Windows.

梦初启 2024-07-22 05:15:42

当我遇到这个在 Arduino 开发人员中流行的解决方案时,我遇到了同样的问题,并且已经考虑编写自己的 php 扩展 - “serproxy”(在很多地方都可以找到它,即 http://www.lspace.nildram.co.uk/freeware.html ) 设置往返于串行端口的 tcp 堆栈并允许我使用 php 套接字函数与其进行通信。

I had the same problem and already considered writing my own php extension when I came across this solution which is popular with Arduino developers - 'serproxy' (found it at many places, ie. http://www.lspace.nildram.co.uk/freeware.html ) sets up a tcp stack to/from the serial ports and allowed me to use the php socket functions to communicate with it.

穿透光 2024-07-22 05:15:42

另一种选择是通过 Windows 上的 ActiveX 使用对象。 Windows 上有多种 COM 串行对象,大部分是商业串行对象。 您还可以公开基于 .Net 的对象并将其注册以供 COM 使用。 当然,这假定您可以控制服务器来注册 COM 控件,因为您需要串行接口。

如果通过 Web 使用,另一个问题是资源争用。 例如,如果这是针对串行打印机,那么打印队列管理器将是直接通信的最佳选择。

Another option is to use an object via ActiveX on windows. There are several, mostly commercial serial objects for COM on windows. You can also expose a .Net based object and register it for COM use as well. Of course, this does presume you have control on the server to register a COM control, as you would need a serial interface.

Another issue is resource contention if this is for use via the Web. If this is for a serial printer, for instance, then a print queue manager would be your best option over direct communication.

贵在坚持 2024-07-22 05:15:42

如果您想使用 com 端口处理短信,那么这里是最著名的 Rémy Sanchez 的 PHP 串行通信课程,带有 Google 示例代码这是一个包含该主题的线程

If you want to deal with sms using com port then here is the most famous php serial communication class by Rémy Sanchez with google sample code. Here is a thread which includes that topic.

温馨耳语 2024-07-22 05:15:42

最大的问题是读取端口。 无论使用哪种方法,stream_get_line()、fgets() 或 dio_read(),它们都工作得很好。

实际上,问题在于此时代码“永远挂起”或“挂起一分钟”,具体取决于“xon”或“to”。

根据多次实验,这种情况发生在没有数据的情况下,因为通常的终端php不起作用,如果没有传入数据,它会在读取时冻结。

这是可以避免的,如上例,向端口发送数据后,执行sleep(time)等待,直到要读取的数据肯定有,这样就会毫无延迟地读取并返回。

The biggest problem is to read the port. And it doesn't matter which method it is done, stream_get_line(), fgets() or dio_read() - they all work great.

Actually the problem is that at this point the code "hangs forever" or "hangs for a minute" depending on "xon" or "to".

According to several experiments, this happens when there is no data, as the usual terminal php does not work, and if there is no incoming data, it freezes on reading.

This can be avoided, as in the example above, after sending data to the port, execute sleep(time) to wait until the data to be read is definitely there, in which case it will be read and returned without any delay.

软糯酥胸 2024-07-22 05:15:42

我使用了 David Refoua 和 Giorgos Pap 的解决方案并进行了一些修改来连接 Arduino UNO。 在 PC 端,我有一个 AJAX 来接收来自 Arduino 的测量结果并以表格形式显示它们。 现在我正在尝试以编程方式更新 COM 端口(在本例中为 COM3),

<?php
$output = exec("mode COM2: BAUD=115200 PARITY=N data=8 stop=1 XON=off TO=on dtr=off odsr=off octs=off rts=on idsr=off");
$fp = fopen("COM2", "r+");
if (!$fp)
{
  exit("Unable to establish a connection");
}
// RX form PC**************
$t = $_POST['text1'];
// TX to Arduino****************
$writtenBytes = fputs($fp, $t);
sleep(1); 
// RX from Arduino**************
$j=0;
$dataset1 = [];
while(!$buffer=stream_get_line($fp,400,"\n")) { 1; }
// TX to PC***************
$piecesa = explode(",", $buffer);
foreach ($piecesa as $value) {  
    $dataset1[$j] = $value;
    $j++;
}
$myJSON = json_encode($dataset1);
echo $myJSON;
fclose($fp);
?>

该程序运行良好,延迟很短,大约 8 秒。 最大限度。 这是Windows操作系统。

I used the solution of David Refoua and Giorgos Pap with some modifications to connect with Arduino UNO. In the PC side, I have an AJAX to receive the measurements from Arduino and show them in a form. Now I am trying to update, programmatically, the COM port (in this case, COM3),

<?php
$output = exec("mode COM2: BAUD=115200 PARITY=N data=8 stop=1 XON=off TO=on dtr=off odsr=off octs=off rts=on idsr=off");
$fp = fopen("COM2", "r+");
if (!$fp)
{
  exit("Unable to establish a connection");
}
// RX form PC**************
$t = $_POST['text1'];
// TX to Arduino****************
$writtenBytes = fputs($fp, $t);
sleep(1); 
// RX from Arduino**************
$j=0;
$dataset1 = [];
while(!$buffer=stream_get_line($fp,400,"\n")) { 1; }
// TX to PC***************
$piecesa = explode(",", $buffer);
foreach ($piecesa as $value) {  
    $dataset1[$j] = $value;
    $j++;
}
$myJSON = json_encode($dataset1);
echo $myJSON;
fclose($fp);
?>

The program is working very well with a short delay, around 8 sec. maximum. This is Windows OS.

兮子 2024-07-22 05:15:41

上述每个解决方案要么效率低下,要么工作量太大。

您只需使用 PHP-DIO 库(dio_fcntl、dio_open、dio_read、 dio_write、dio_seek、...)。 它也在 DIO 的 PHP 手册条目中:

此 PECL 包是默认情况下不可用。 如果您的 PHP 5.2.x 高于 5.2.6,要获取 Windows 版,您可以将其作为 ZIP 的一部分下载:

两者这些链接位于 http://www.deveblog .com/index.php/download-pecl-extensions-for-windows/

这里是从 Linux 构建,只需获取它并执行 phpize/configure/make/make install 即可。

我不知道它是否应该在 Apache 会话中使用,但是就用吧。

Every solution above is either inefficient or too much work.

You can just use the PHP-DIO library (dio_fcntl, dio_open, dio_read, dio_write, dio_seek, ...). It's also in the PHP manual's entry for DIO:

This PECL package isn't available by default. To get it for Windows if you have PHP 5.2.x greater than 5.2.6, you can download it as part of a ZIP:

Both of these links were found in http://www.deveblog.com/index.php/download-pecl-extensions-for-windows/

Here is the build from Linux, just get it and do the phpize/configure/make/make install thing.

I don't know whether it should be used in an Apache session, but go for it.

凑诗 2024-07-22 05:15:41

您需要使用类似 DOS 的命令来设置 com 端口。

例如,以下行通过 php 执行命令:

$output = `mode COM1: BAUD=115200 PARITY=N data=8 stop=1 XON=off TO=on`;

要显示结果,您可以使用:

echo "$output"; 

创建资源 id:

$fp = fopen('COM1', 'r+');

if (!$fp)
{
      echo "Port not accessible";
}
else
{
     echo "Port COM1 opened successfully";
}

写入端口:

$writtenBytes = fputs($fp, "Hello");

echo"Bytes written to port: $writtenBytes";

从端口读取:

$buffer = fgets($fp);

echo "Read from buffer: $buffer";

也许有人可以帮助我解决 fgets 问题。 如果TO=on,它会在那里堆叠一分钟;如果TO=off,它会永远堆叠在那里。 它似乎是一个“MODE COM”选项,所以也许 DOS 专家可以提供帮助。

也许应该使用 fgetc 而不是 fgets,因为 fgets 捕获到 newline,而 fgetc 捕获单个字符。 如果没有遇到新行,它可能会阻塞,直到出现新行或刷新缓冲区为止。 一分钟的延迟可能是窗口每隔一段时间刷新其缓冲区。

You need to set up the com port using a DOS-like command.

For example, the following line executes the command through php:

$output = `mode COM1: BAUD=115200 PARITY=N data=8 stop=1 XON=off TO=on`;

To display the results you can use:

echo "$output"; 

Create the resource id:

$fp = fopen('COM1', 'r+');

if (!$fp)
{
      echo "Port not accessible";
}
else
{
     echo "Port COM1 opened successfully";
}

Write to port:

$writtenBytes = fputs($fp, "Hello");

echo"Bytes written to port: $writtenBytes";

Read from port:

$buffer = fgets($fp);

echo "Read from buffer: $buffer";

Maybe someone can help me with the fgets problem. It stacks there for exactly one minute if TO=on, or stacks there forever if TO=off. It seems to be a "MODE COM" option so maybe a DOS expert can help.

Perhaps instead of fgets, one should use fgetc, since fgets capture through to the newline, while fgetc captures a single character. If a new line isn't encountered, it may block until there is one or until the buffer is flushed. The one minute delay may be windows flushing its buffer on an interval.

小嗷兮 2024-07-22 05:15:41

解决这个问题的最简单方法是用另一种语言(例如 C++)编写程序,然后使用 system() 从 php 脚本执行它。 在 C++ 中进行 Comm I/O 很简单。

这假设您有足够的服务器访问权限来配置它以允许可执行文件由 php 等运行。

The easiest way to tackle this would be to write a program in another language (such as C++) and then execute it from your php script with system(). Doing Comm I/O in C++ is trivial.

This assumes you have enough access to the server to configure it to allow the executable to be run by php, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文