php串口通信怎么设置_php调用dio扩展读写串口数据【方法】

dio扩展因未适配PHP 7+的Zend Engine 2架构而失效,官方已移除支持;替代方案包括用proc_open调用stty/cat/echo操作串口设备文件,或通过PHP调用Python pyserial脚本实现可靠通信。

PHP 本身不原生支持串口通信,dio 扩展是早期 Linux/Unix 下较常用的方案,但已多年未维护(最后更新在 PHP 5.6 时代),在 PHP 7.4+ 及现代系统上基本不可用。直接启用 dio 扩展会报 undefined function dio_open() 或编译失败。

为什么 dio 扩展在新 PHP 版本中无法使用

dio 扩展依赖 PHP 内部 ZE1 时代的资源管理机制和旧版 API,在 PHP 7 引入 Zend Engine 2 后大量结构被重写,其源码未适配。即使强行编译通过,运行时也极易触发段错误或资源泄漏。

  • PHP 7.0+ 官方已移除对 dio 的构建支持
  • Debian/Ubuntu 的 php-dio 包仅存在于 oldstable(如 buster)且只对应 PHP 7.3 及更早
  • Windows 下无官方 dio DLL,PECL 页面明确标注 “Not maintained”

替代方案:用 proc_open + stty + cat/echo 操作串口设备文件

Linux 下串口本质是文件(如 /dev/ttyUSB0),PHP 可通过进程控制绕过扩展限制,关键在于正确设置终端参数。

  • 先用 stty 配置波特率、数据位、停止位、校验等:
    stty -F /dev/ttyUSB0 9600 cs8 -cstopb -parenb
  • 读取时避免阻塞:加 -icanon -echo -echoe -echok 并设 min 0 time 0
  • PHP 中用 proc_open 启动 catdd 读取,用 echo 写入
  • 务必检查串口权限:sudo usermod -a -G dialout $USER,否则会报 Permission denied

稳定方案:改用 Python 脚本 + PHP 调用

用 Python 的 pyserial 库处理串口最可靠,PHP 只负责调用和解析结果。

  • 写一个 serial_io.py
    #!/usr/bin/env python3
    import serial
    import sys
    port, baud, cmd = sys.argv[1], int(sys.argv[2]), sys.argv[3]
    ser = serial.Serial(port, baud, timeout=1)
    if cmd == 'read':
        print(ser.read(64).hex())
    elif cmd == 'write':
        ser.write(bytes.fromhex(sys.argv[4]))
    ser.close()
  • PHP 中调用:$output = shell_exec("python3 serial_io.py /dev/ttyUSB0 9600 read");
  • 注意:确保 Web 用户(如 www-data)有串口设备读写权限,或用 sudoers 授权特定命令

真正麻烦的不是“怎么读”,而是串口参数错一位(比如把 cs8 写成 cs7)、权限没放开、或 Python 脚本路径没写绝对路径——这些细节卡住的时间,远超写代码本身。