计算机控制系统:HX1838红外遥控器解码

1 硬件

  相关说明:hx1838 红外遥控(1):接收时序的解码-优快云博客

接线图:

2 解码原理

红外遥控器采用了NEC编码规则:

NEC 载波频率为 38Khz
引导码:9ms 高电平 + 4.5ms 低电平
1 码 :0.56 ms 高电平 + 0.56 ms 低电平
0 码 : 0.56ms 高电平 + 1.68 ms 低电平
结束码 :0.56ms 高电平
数据帧格式:引导码 + 地址 + 地址反码 + 键值 + 键值反码 + 结束码
重复帧格式:9ms 高电平 + 2.25ms低电平 + 结束位 + 结束码
高位在前,即首先收到的是高位的数据
 

3 代码

实际接线 接的D8 用于解析

手动的红外遥控器是小孩的,可以接收,但无法解码:

 
等待空闲状态...
等待引导脉冲...
未知协议特征(低:13.90ms, 高:29.83ms)
捕获信号中...

代码如下:

% 增强版红外解码程序 - 解决解码失败问题

% 初始化Arduino对象
clear  
a = arduino('COM5', 'Uno'); % 修改为你的端口和板型
configurePin(a, 'D8', 'DigitalInput');

% 增强参数配置
irPin = 'D8';          % 红外接收模块连接的引脚
timeout = 0.5;         % 延长等待信号的超时时间
sampleInterval = 20e-6; % 更精细的采样间隔(20微秒)
minPulseDuration = 1e-4; % 最小脉冲持续时间(100微秒)

% 创建图形窗口
% figure;
% subplot(2,1,1);
% hWave = stairs(0,0);
% title('红外信号波形');
% xlabel('时间(ms)');
% ylabel('电平');
% ylim([-0.1 1.1]);
% grid on;
% 
% subplot(2,1,2);
% hBits = stem(zeros(1,32));
% title('解码位值');
% ylim([-0.1 1.1]);
% xlim([0 33]);
% grid on;

% 主循环
while true
    fprintf('\n等待红外信号...\n');
    
    % 增强的引导脉冲检测
    [pulseTimes, pulseValues, success] = waitAndCapture(a, irPin, timeout, sampleInterval);
    if ~success
        continue;
    end
    
    % 绘制信号波形
%     plotIRSignal(hWave, pulseTimes, pulseValues);
    
    % 增强的解码函数
    [address, command, isRepeat, bits] = decodeNEC_enhanced(pulseTimes, pulseValues)
    
    % 显示位值
%     set(hBits, 'YData', bits);
    
    % 显示解码结果
    if ~isempty(address)
        if isRepeat
            fprintf('重复键: 地址=0x%02X, 命令=0x%02X\n', address, command);
        else
            fprintf('新按键: 地址=0x%02X (反码:0x%02X), 命令=0x%02X (反码:0x%02X)\n',...
                    address, bitcmp(address,8), command, bitcmp(command,8));
        end
    else
        fprintf('解码失败 - 可能原因:\n');
        fprintf('1. 遥控器不是NEC协议\n');
        fprintf('2. 距离太远或角度不对\n');
        fprintf('3. 环境光干扰太强\n');
        
        % 显示信号统计信息辅助调试
        fprintf('信号统计: 持续时间=%.2fms, 脉冲数=%d\n',...
                (pulseTimes(end)-pulseTimes(1))*1000, length(pulseTimes));
    end
    drawnow;
end

% 释放Arduino对象
clear  

%% 增强的信号捕获函数

function [times, values, success] = waitAndCapture(a, pin, timeout, interval)
    times = [];
    values = [];
    success = false;
    
    % 等待空闲状态(持续高电平)
    fprintf('等待空闲状态...\n');
    idleStart = tic;
    while toc(idleStart) < timeout
        if readDigitalPin(a, pin) == 1
            break;
        end
        pause(interval*5);
    end
    
    % 等待引导脉冲开始(低电平)
    fprintf('等待引导脉冲...\n');
    startTime = tic;
    while toc(startTime) < timeout
        if readDigitalPin(a, pin) == 0
            break;
        end
        pause(interval);
    end
    
    % 记录引导脉冲持续时间
    pulseStart = tic;
    while readDigitalPin(a, pin) == 0
        if toc(pulseStart) > 0.015 % NEC引导脉冲最长9ms
            fprintf('无效引导脉冲\n');
            return;
        end
    end
    leadLow = toc(pulseStart);
    
    % 检查引导脉冲是否符合NEC标准(4.5ms或2.25ms)
    if leadLow < 0.008 || leadLow > 0.010
        fprintf('非标准引导脉冲: %.2fms\n', leadLow*1000);
        return;
    end
    
    % 开始捕获完整信号
    fprintf('捕获信号中...\n');
    maxDuration = 0.1; % 最大捕获时长100ms
    bufferSize = ceil(maxDuration / interval);
    
    times = zeros(bufferSize, 1);
    values = zeros(bufferSize, 1);
    
    times(1) = 0;
    values(1) = 0; % 引导脉冲低电平开始
    
    captureStart = tic;
    lastTime = 0;
    lastValue = 0;
    idx = 2;
    
    while toc(captureStart) < maxDuration && idx <= bufferSize
        currentValue = readDigitalPin(a, pin);
        currentTime = toc(captureStart);
        
        if currentValue ~= lastValue
            times(idx) = currentTime;
            values(idx) = currentValue;
            lastValue = currentValue;
            idx = idx + 1;
        end
        
        pause(interval);
    end
    
    % 裁剪数组
    times = times(1:idx-1);
    values = values(1:idx-1);
    
    % 检查捕获的信号是否有效
    if length(times) < 10
        fprintf('捕获信号太短\n');
        return;
    end
    
    success = true;
end

%% 增强的NEC解码函数
function [address, command, isRepeat, bits] = decodeNEC_enhanced(times, values)
    address = [];
    command = [];
    isRepeat = false;
    bits = zeros(1,32);
    
    % 计算各脉冲持续时间
    durations = diff(times);
    
    % 检查是否为重复码
    if length(durations) < 10
        totalTime = times(end) - times(1);
        if totalTime > 0.009 && totalTime < 0.015 % 重复码特征
            isRepeat = true;
            return;
        else
            fprintf('无效信号长度\n');
            return;
        end
    end
    
    % 查找数据位开始位置(跳过引导脉冲)
    dataStart = 3; % 通常第3个脉冲开始数据
    
    % 提取32位数据
    bitCount = 0;
    for i = dataStart:2:min(dataStart+63, length(durations)-1)
        zeroBit = durations(i) < 0.0012; % 560us低+560us高=0
        oneBit = durations(i) < 0.0012 && durations(i+1) > 0.0012; % 560us低+1690us高=1
        
        if oneBit
            if bitCount < 32
                bits(bitCount+1) = 1;
            end
            bitCount = bitCount + 1;
        elseif zeroBit
            if bitCount < 32
                bits(bitCount+1) = 0;
            end
            bitCount = bitCount + 1;
        else
            fprintf('无效脉冲宽度: %.2fms\n', durations(i)*1000);
        end
    end
    
    % 检查是否获取了完整32位数据
    if bitCount < 32
        fprintf('数据不完整: 只收到%d位\n', bitCount);
        return;
    end
    
    % 解码地址和命令
    address = bin2dec(num2str(bits(1:8)));
    invAddress = bin2dec(num2str(bits(9:16)));
    command = bin2dec(num2str(bits(17:24)));
    invCommand = bin2dec(num2str(bits(25:32)));
    
    % 验证反码
    if (bitcmp(address,8) ~= invAddress) || (bitcmp(command,8) ~= invCommand)
        fprintf('反码验证失败\n');
        address = [];
        command = [];
        return;
    end
end

%% 信号绘图函数
function plotIRSignal(h, times, values)
    timesMs = times * 1000;
    
    % 创建阶梯图数据
    x = zeros(2*length(timesMs),1);
    y = zeros(2*length(timesMs),1);
    
    for i = 1:length(timesMs)
        x(2*i-1) = timesMs(i);
        x(2*i) = timesMs(i);
        y(2*i-1) = values(i);
        y(2*i) = values(i);
    end
    
    set(h, 'XData', x, 'YData', y);
    xlim([0 max(timesMs)]);
    title(sprintf('红外信号波形 (持续时间: %.2fms)', max(timesMs)));
end

<think>好的,我现在要帮用户查找HX1838红外遥控的编码值相关信息,包括数据格式和协议。首先,我需要回忆用户提供的引用内容,看看有没有直接相关的信息。引用1提到HX1838接收的是标准38KHz调制的信号,解码成十六进制码。引用2提到遥控按键按下会发送一组脉冲,使用NEC编码格式。引用3明确说明HX1838采用的是NEC编码格式,主要用于车载MP3等设备。 接下来,我需要确认NEC编码的具体格式。根据已有的知识,NEC协议通常使用38KHz载波,数据帧包括引导码、地址码、地址反码、命令码和命令反码。每个字节是LSB优先,脉冲间隔表示0和1。引导码是一个9ms的高电平和4.5ms的低电平。数据位中的逻辑0是560us高电平加560us低电平,逻辑1是560us高电平加1680ms低电平。此外,可能会有重复码,用于长按按键的情况。 现在要检查引用中是否有提到这些细节。引用2提到高低电平的变化,可能对应引导码和数据位的描述。引用3明确指出是NEC编码,但没详细说明数据格式。因此,需要结合通用NEC协议的信息,并确认HX1838是否遵循相同的标准。 用户可能需要具体的编码示例,比如某个按键对应的十六进制值。但引用中没有提供具体的键值表,可能需要建议用户查阅厂商文档或使用逻辑分析仪捕获信号。 最后,确保回答结构清晰,分点说明协议、数据格式、示例和注意事项,并引用提供的资料。同时生成相关问题,帮助用户进一步了解解码实现或应用场景。</think>根据提供的参考资料,HX1838红外遥控采用NEC编码格式,其数据协议和编码值结构如下: ### 一、NEC协议框架 1. **载波频率**:38KHz调制信号[^1][^3] 2. **数据帧结构**(典型NEC格式): $$引导码(9ms\高电平+4.5ms\低电平)+地址码(8bit)+地址反码(8bit)+命令码(8bit)+命令反码(8bit)$$ ### 二、编码值解析 1. **位表示方法**: - 逻辑0:560μs高电平 + 560μs低电平 - 逻辑1:560μs高电平 + 1680μs低电平 - 重复码:9ms高电平 + 2.25ms低电平 + 560μs高电平(用于长按键操作)[^2] 2. **数据方向**: - 采用LSB(Least Significant Bit)优先传输方式 - 每个字节低位在前,高位在后 ### 三、典型数据示例 某按键按下时的完整数据帧: ``` 引导码 -> 地址码0x00 -> 地址反码0xFF -> 命令码0x15 -> 命令反码0xEA ``` 此时接收端解码结果为十六进制值:`0x15` ### 四、特殊说明 1. 不同厂商可能自定义地址码,需通过逻辑分析仪或示波捕获实际波形 2. 重复码间隔约108ms,用于检测持续按键操作 3. 接收头输出信号已解调为TTL电平,可直接由MCU捕获[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

做一个码农都是奢望

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值