树莓派环境下如何用PHP读取实时RS232串口数据并更新至网页
解决方案
1. 先配置串口通讯参数
你之前读取到无标签的异常数据、fgets无返回,核心原因是没有给USB转串口设备配置匹配的通讯参数。直接在系统层配置即可,无需额外PHP扩展:
- 执行命令配置串口参数,匹配你设备的57600-N-8-1规格:
stty -F /dev/ttyUSB0 57600 cs8 -cstopb -parenb - 可将上述命令写入
/etc/rc.local实现开机自动配置,避免重启后参数失效。
2. 拆分读写逻辑,规避超时和冲突问题
你之前报错30秒超时、多请求占用串口的问题,是因为将串口读取逻辑直接放到了Web访问的PHP脚本中。建议拆分逻辑:用CLI模式跑后台常驻进程读串口,数据写入内存缓存,Web端只读缓存,完全避免SD卡读写,也不会有执行超时问题。
Debian系统默认自带/dev/shm内存文件系统,所有读写都在内存中完成,不占用SD卡寿命,完全满足你的需求。
后台串口读取脚本(meter_read.php)
<?php // 取消CLI脚本执行时间限制 set_time_limit(0); // 确认串口参数生效 exec('stty -F /dev/ttyUSB0 57600 cs8 -cstopb -parenb'); $device = "/dev/ttyUSB0"; $fp = fopen($device, "r") or die("串口设备打开失败"); // 设为阻塞模式,fgets会等到完整行(\r\n结尾)才返回 stream_set_blocking($fp, true); while (true) { $xml = trim(fgets($fp)); // 过滤无效数据,仅保留合法的XML报文 if (!empty($xml) && str_starts_with($xml, '<msg>')) { // 可在此处添加XML解析逻辑,提取温度、各通道功率等字段 $output = [ 'raw_xml' => $xml, 'update_time' => date('Y-m-d H:i:s') ]; // 写入内存盘,完全不涉及SD卡读写 file_put_contents('/dev/shm/meter_data.json', json_encode($output, JSON_UNESCAPED_UNICODE)); } // 匹配设备6秒上报一次的频率,降低CPU占用 sleep(6); } fclose($fp); ?>
- 后台启动脚本命令:
nohup php /你的脚本路径/meter_read.php > /dev/null 2>&1 & - 可将上述启动命令加入开机自启,实现开机自动运行数据采集进程。
Web端展示脚本(index.php)
Web端无需操作串口,直接读取内存中的缓存数据即可:
<?php $data_path = '/dev/shm/meter_data.json'; if (file_exists($data_path)) { $data = json_decode(file_get_contents($data_path), true); // 此处可根据需求自行渲染页面展示数据 print_r($data); } else { echo "数据初始化中,请稍候重试"; } ?>
常见问题说明
- 之前
fgets无法读取数据:是因为串口参数不匹配时,报文末尾的\r\n无法被系统正确识别,fgets会一直等待换行符,看起来就没有返回值,配置正确stty参数后即可正常读取。 - 不需要使用已经废弃的PECL-DIO扩展,也不需要第三方串口类,纯PHP配合系统
stty命令即可满足需求。 - 后台进程只占用极低的系统资源,单进程常驻不会影响树莓派的正常运行。
内容的提问来源于stack exchange,提问作者Sabreur
相关产品推荐
相关产品推荐

