本文目录导读:

- 使用 PHP Serial 扩展(推荐)
- 使用
dio扩展(Direct I/O) - 使用
exec()调用系统命令 - 使用 file functions(文件操作)
- 封装一个完整的串口类
- 异步通信示例
- 注意事项
PHP 进行串口通信主要通过以下几种方式实现,我来详细介绍:
使用 PHP Serial 扩展(推荐)
安装扩展
# Ubuntu/Debian sudo apt-get install php-dev git clone https://github.com/Xowap/PHP-Serial.git cd PHP-Serial phpize ./configure make sudo make install # 在 php.ini 中添加 extension=php_serial.so
基本使用示例
<?php
include 'php_serial.class.php';
// 创建串口对象
$serial = new phpSerial();
// 设置串口参数
$serial->deviceSet('/dev/ttyUSB0'); // Linux/Mac
// $serial->deviceSet('COM3'); // Windows
// 配置串口
$serial->confBaudRate(9600); // 波特率
$serial->confParity('none'); // 校验位
$serial->confCharacterLength(8); // 数据位
$serial->confStopBits(1); // 停止位
$serial->confFlowControl('none'); // 流控制
// 打开串口
$serial->deviceOpen();
// 发送数据
$serial->sendMessage("Hello Serial!");
$serial->sendMessage(chr(0x01) . chr(0x02)); // 发送二进制数据
// 读取数据
$read = $serial->readPort();
$read = $serial->readPort(10); // 读取10个字符
// 关闭串口
$serial->deviceClose();
?>
使用 dio 扩展(Direct I/O)
安装扩展
# Ubuntu/Debian sudo apt-get install php-dio
使用示例
<?php
// 打开串口
$fd = dio_open('/dev/ttyS0', O_RDWR | O_NOCTTY | O_NONBLOCK);
// 设置串口参数
dio_fcntl($fd, F_SETFL, O_RDWR | O_NONBLOCK);
// 配置串口
dio_tcsetattr($fd, array(
'baud' => 9600,
'bits' => 8,
'stop' => 1,
'parity' => 0
));
// 写入数据
$data = "Hello Serial!";
dio_write($fd, $data);
// 读取数据
$input = dio_read($fd, 1024);
// 关闭串口
dio_close($fd);
?>
使用 exec() 调用系统命令
Linux 使用 stty 和 cat/echo
<?php
// 配置串口
exec('stty -F /dev/ttyUSB0 9600 cs8 -cstopb -parenb');
exec('stty -F /dev/ttyUSB0 raw');
// 发送数据
$fp = fopen('/dev/ttyUSB0', 'w');
fwrite($fp, "Hello Serial!");
fclose($fp);
// 或使用 echo
exec('echo "Hello" > /dev/ttyUSB0');
// 读取数据
$fp = fopen('/dev/ttyUSB0', 'r');
$data = fread($fp, 1024);
fclose($fp);
?>
使用 file functions(文件操作)
<?php
// Windows 环境
$comPort = "COM3";
exec("mode " . $comPort . " BAUD=9600 PARITY=N data=8 stop=1 xon=off");
// 打开串口
$fp = fopen("\\\\\\\\.\\\\" . $comPort, "r+");
if (!$fp) {
die("无法打开串口");
}
// 设置非阻塞模式
stream_set_blocking($fp, 0);
// 发送数据
fwrite($fp, "Hello Serial!");
// 读取数据
$data = fread($fp, 1024);
// 关闭串口
fclose($fp);
?>
封装一个完整的串口类
<?php
class SerialPort {
private $device;
private $baudRate;
private $handle;
public function __construct($device = '/dev/ttyUSB0', $baudRate = 9600) {
$this->device = $device;
$this->baudRate = $baudRate;
}
public function open() {
// 使用 exec 配置串口
exec("stty -F " . $this->device . " " . $this->baudRate . " cs8 -cstopb -parenb raw");
// 打开设备
$this->handle = fopen($this->device, 'w+');
if (!$this->handle) {
throw new Exception("无法打开串口设备");
}
// 设置非阻塞模式
stream_set_blocking($this->handle, 0);
return true;
}
public function send($data) {
if (!$this->handle) return false;
return fwrite($this->handle, $data);
}
public function receive($length = 1024) {
if (!$this->handle) return false;
return fread($this->handle, $length);
}
public function close() {
if ($this->handle) {
fclose($this->handle);
$this->handle = null;
}
}
public function flush() {
exec("stty -F " . $this->device . " -echo");
}
}
// 使用示例
try {
$serial = new SerialPort('/dev/ttyUSB0', 9600);
$serial->open();
// 发送数据
$serial->send("AT\r\n");
// 等待响应
usleep(500000); // 500ms
// 接收数据
$response = $serial->receive();
echo "Response: " . $response . "\n";
$serial->close();
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
}
?>
异步通信示例
<?php
// 使用非阻塞模式进行异步通信
$fp = fopen('/dev/ttyUSB0', 'r+');
stream_set_blocking($fp, 0);
// 发送多个命令
$commands = array("ATZ", "ATI", "ATE0");
foreach ($commands as $cmd) {
fwrite($fp, $cmd . "\r\n");
usleep(200000); // 200ms
$response = fread($fp, 4096);
echo "发送: " . $cmd . "\n";
echo "接收: " . $response . "\n---\n";
}
fclose($fp);
?>
注意事项
-
权限问题:Linux 下需要给用户添加
dialout组权限sudo usermod -a -G dialout $USER
-
超时设置:可以设置超时避免阻塞
stream_set_timeout($fp, 1); // 1秒超时
-
调试方法:
// 添加错误处理 if (!$fp) { error_log("无法打开串口", 3, "/var/log/serial.log"); }
// 查看串口状态 exec('dmesg | grep ttyS0'); exec('ls -l /dev/ttyUSB*');
4. **性能考虑**:对于高频率通信,建议使用 PHP 扩展或 C/C++ 扩展
选择哪种方式取决于:
- 你的 PHP 环境(是否有权限安装扩展)
- 平台(Linux/Windows)
- 性能需求
- 通信的稳定性要求
对于项目开发,推荐使用 **PHP-Serial 扩展** 或封装的类,它们提供了更可靠的通信机制。