导读:本期聚焦于桃乃木香奈创作的《php读取红外遥控信号怎么弄_php捕获红外接收头的解码数据【操作】》,敬请观看详情。树莓派或单片机接了红外接收头,想用PHP把遥控器按键的编码读出来,该从哪里下手?红外接收头输出的其实是一串脉冲信号,需要按照协议规则测量每个脉冲的宽度和间隔,才能还原出原始数据。本文介绍两种常见做法:一是直接读取GPIO电平变化并计时,用PHP的文件系统接口操作sysfs或借助shell调用外部工具完成解码;二是使用现成的LIRC软件负责底层解码,PHP通过socket读取解析好的键值,再映射成自己的业务逻辑。文章还会讲解NEC协议的引导码、数据位表示方法,以及32位编码中用户码与键码的区分方式,最后附上数据校验、防抖动和长按重复码的处理技巧,帮助你把遥控信号稳定地接入PHP应用。

红外遥控是最常见的无线控制方式之一,电视、空调、机顶盒的遥控器都依赖它。如果我们在树莓派或者安装了红外接收头的服务器上跑PHP项目,想把遥控器的按键读进来触发一些动作,比如控制网页翻页、切换灯光状态,就绕不开红外信号的捕获和解码问题。红外信号本质上是一串有规律的电平脉冲,硬件只负责把38kHz载波解调成高低电平,软件层面需要测量这些电平持续的时间,才能还原出遥控器发出来的原始数据。下面详细介绍具体的实现思路和代码。

php读取红外遥控信号怎么弄_php捕获红外接收头的解码数据【操作】

一、红外信号的基本原理与NEC协议格式

红外接收头(如VS1838B、HS0038B)内部集成了光电探测、放大、滤波和解调电路,它输出的信号与遥控器发出的信号是反相关系:遥控器发射时,接收头输出低电平;没有信号时输出高电平。因此软件读到的数据是一串高低电平交替的脉冲序列。

目前家用遥控器最常见的是NEC协议,它的帧结构比较简单:先是一段9ms的低电平加4.5ms的高电平作为引导码,随后跟32位数据。数据位用不同的脉冲宽度区分,逻辑0是560微秒低电平加560微秒高电平,逻辑1是560微秒低电平加1.68毫秒高电平。32位数据由16位用户码、8位键码和8位键码反码组成,反码的作用是校验数据完整性。

当按键持续按下时,NEC协议每110毫秒发送一次重复码,波形是9ms低电平加2.25ms高电平加560微秒低电平。程序在解码时必须把重复码与正常数据帧区分开,否则长按操作会被误判成连续的独立按键。

二、PHP直接读取GPIO电平并解码

如果使用树莓派,PHP可以通过sysfs接口直接读取GPIO电平。虽然PHP不是实时性最好的语言,测量微秒级脉冲有一定误差,但通过多次采样取平均值,解码NEC协议这种毫秒级信号是可行的。PHP提供了system()exec()file_get_contents()等函数,可以结合底层工具完成测量。

下面是一段PHP示例代码,通过调用gpio命令或者直接读写sysfs来轮询电平,并用microtime(true)记录跳变时刻,把脉冲宽度序列转成二进制数据:

<?php
// 红外接收头数据脚接树莓派GPIO17,即sysfs编号17
$gpioPin = 17;

// 初始化GPIO为输入模式
@file_put_contents("/sys/class/gpio/export", $gpioPin);
usleep(100000);
@file_put_contents("/sys/class/gpio/gpio{$gpioPin}/direction", "in");

/**
 * 读取当前电平
 */
function readLevel($pin) {
    return trim(file_get_contents("/sys/class/gpio/gpio{$pin}/value"));
}

/**
 * 等待引导码:9ms低电平 + 4.5ms高电平
 * 返回true表示捕获到一帧数据,false表示超时
 */
function waitLeader($pin, $timeoutSec = 2) {
    $start = microtime(true);
    while ((microtime(true) - $start) < $timeoutSec) {
        if (readLevel($pin) == '0') {
            $t = microtime(true);
            // 测量低电平持续时间
            while (readLevel($pin) == '0') {
                if (microtime(true) - $t > 0.02) return false;
            }
            $low = microtime(true) - $t;
            // 低电平约9ms则可能是引导码
            if ($low > 0.007 && $low < 0.012) {
                return true;
            }
        }
        usleep(50);
    }
    return false;
}

/**
 * 读取32位数据,根据高电平宽度判断0和1
 */
function readFrame($pin) {
    $bits = '';
    for ($i = 0; $i < 32; $i++) {
        // 等待低电平结束
        while (readLevel($pin) == '0') {}
        $t = microtime(true);
        // 测量高电平宽度
        while (readLevel($pin) == '1') {}
        $high = microtime(true) - $t;
        // 高电平大于1ms判定为逻辑1,否则为逻辑0
        $bits .= ($high > 0.0011) ? '1' : '0';
    }
    return $bits;
}

// 主循环:持续监听红外信号
while (true) {
    if (waitLeader($gpioPin)) {
        $bits = readFrame($gpioPin);
        if (strlen($bits) == 32) {
            $userCode = bindec(substr($bits, 0, 16));
            $keyCode = bindec(substr($bits, 16, 8));
            $keyInv  = bindec(substr($bits, 24, 8));
            // 校验键码与反码
            if ((($keyCode ^ $keyInv) & 0xFF) == 0xFF) {
                printf("用户码: %04X  键码: %02X\n", $userCode, $keyCode);
            }
        }
    }
    usleep(1000);
}

这段代码的核心思路是利用microtime(true)获取浮点时间戳,两次读取之间的差值就是脉冲宽度。需要注意的是,PHP的解释执行特性会带来几十微秒的抖动,所以判断阈值要留出足够的容差区间,比如逻辑1的高电平实际是1.68ms,阈值设为1.1ms,逻辑0是0.56ms,两者之间有明显间隔,一般不会误判。

直接读取方式的好处是不依赖额外软件,代码可控;缺点是对系统负载敏感,如果PHP进程被调度打断,可能丢失一帧数据。因此建议在空闲的系统上运行,并在解码失败时静默丢弃该帧,等待下一次按键重试。

三、使用LIRC解码,PHP负责业务逻辑

更稳妥的方案是使用LIRC(Linux Infrared Remote Control)。LIRC是Linux下成熟的红外处理框架,支持内核级精确计时,解码工作全部由C代码完成,PHP只需读取解析结果。树莓派上可以通过apt-get install lirc安装,并在配置文件中把GPIO17指定为输入引脚。

安装配置好LIRC后,先用irrecord工具录制遥控器的编码,生成配置文件。之后LIRC会以守护进程方式运行,通过/var/run/lirc/lircd这个unix socket对外输出按键事件。PHP可以使用stream_socket_client连接这个socket,实时读取按键名称:

<?php
// 连接LIRC的unix socket
$sock = stream_socket_client("unix:///var/run/lirc/lircd", $errno, $errstr);
if (!$sock) {
    die("连接LIRC失败: $errstr\n");
}

// 把键码映射成业务动作
$actionMap = [
    'KEY_UP'    => 'pagePrev',
    'KEY_DOWN'  => 'pageNext',
    'KEY_OK'    => 'togglePlay',
    'KEY_POWER' => 'shutdown',
];

echo "等待红外按键...\n";
while (true) {
    $line = fgets($sock);
    if ($line === false) {
        // socket断开,稍后重连
        sleep(1);
        $sock = stream_socket_client("unix:///var/run/lirc/lircd", $e2, $s2);
        continue;
    }
    // LIRC输出格式: 按键码 重复次数 遥控器名 按键名
    $parts = preg_split('/\s+/', trim($line));
    if (count($parts) > 2) {
        $repeat = intval($parts[1]);
        if ($repeat > 0) {
            // 重复码,长按中,可忽略或做连续调节
            continue;
        }
        $keyName = $parts[2];
        if (isset($actionMap[$keyName])) {
            echo "触发动作: " . $actionMap[$keyName] . "\n";
            // 这里可以调用项目逻辑,比如发送HTTP请求控制前端页面
        }
    }
}

这种架构把实时性要求高的解码工作交给C语言实现的LIRC,PHP专注于业务处理,稳定性比直接轮询GPIO高得多。代码中通过判断重复次数字段来过滤长按产生的重复码,只有第一次按键才触发动作,符合大多数遥控交互的习惯。

四、常见问题与调试技巧

调试红外解码时,第一步要确认硬件连接正确。接收头有三个引脚:OUT接GPIO、GND接地、VCC接3.3V,三个脚不能接反,接反可能烧毁器件。如果读到的电平一直是0或一直是1,先用手机摄像头对准遥控器发射管按键观察是否有亮点,排除遥控器本身的问题。

解码不稳定时可以在每帧之间增加确认逻辑,比如连续两次读到相同键码才认定有效,这样能过滤掉偶发的干扰脉冲。另外注意系统负载问题,跑PHP解码进程时尽量避免同时执行重计算任务,必要时可以给进程提高调度优先级,用nice或者renice命令调整。

最后建议把解码逻辑封装成独立的守护进程,通过消息队列或者HTTP接口把按键事件推送给Web应用,这样PHP-FPM管理的网页和硬件解码层完全解耦,部署和排查问题都会轻松很多。整体来看,个人实验项目用GPIO轮询方式简单直接,生产环境则优先选择LIRC方案。

php红外解码红外接收头NEC协议修改时间:2026-09-02 11:24:58

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编写,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260902/48897.html,基于非商业使用的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。