Tank2535 发表于 2025-3-11 17:45:38

关于NEC遥控器重复码的识别

       各位兄弟,请教一下NEC遥控器重复码的识别。也就是长按是如何实现的?做了很多用到遥控器类的产品,一直没有用到长按功能,现在有客户提出来用长按实现连加、连减。我试着读取2.25ms的重复码,可以正常读取,但是不能实现长按功能,汗!有例程的兄弟不吝赐教!谢谢!

_奶咖君_ 发表于 2025-3-11 17:50:09

保存一下最后一个键值码,,如果读取到是重复码就把上一次的键值码发送给应用层

Tank2535 发表于 2025-3-11 18:46:27

_奶咖君_ 发表于 2025-3-11 17:50
保存一下最后一个键值码,,如果读取到是重复码就把上一次的键值码发送给应用层 ...

键值码,短按的时候也是必须保存的。

王昱顺 发表于 2025-3-11 18:57:37

Tank2535 发表于 2025-3-11 18:46
键值码,短按的时候也是必须保存的。
做一个连续检测长度判断,每隔一段时间,例如200ms,判断当前是否还有新接收的键值码。
如果还有的话就判断是否跟上次连续一致,等待多次连续后(例如三次重复)就开始以固定间隔连续改变需要设置的变量(例如数值的连续自加)。
如果判断跟上次不一样,就重新开始200ms计时并清除重复计数

Tank2535 发表于 2025-3-11 19:52:50

王昱顺 发表于 2025-3-11 18:57
做一个连续检测长度判断,每隔一段时间,例如200ms,判断当前是否还有新接收的键值码。
如果还有的话就判 ...

这样也行?32位码,如果连按就出错了

王昱顺 发表于 2025-3-11 20:01:55

Tank2535 发表于 2025-3-11 19:52
这样也行?32位码,如果连按就出错了

连按不影响长按识别,只有检测到重复码才开始200ms(或者其他长度,需要长一点)的计时,计时到了再进行重复判别
如果按下了其他按键,可以直接清空计时,这样只有在长按的时候才有连加反应
具体效果应该是按下+按键,立刻加1,等待识别到重复码超过指定时间长度(长按了一会)然后再开始连续自加

xxkj2010 发表于 2025-3-11 20:36:23

以下内容来自AI,不知道是否可以参考



为了实现NEC遥控器的长按功能(连加/连减),需要正确处理重复码的时序和状态机。以下是基于STC8H单片机的实现思路和示例代码:NEC协议长按原理
[*]首次按键:发送完整数据帧(引导码+用户码+键码)
[*]长按期间:每110ms发送一个重复码(9ms低电平+2.25ms高电平)
[*]按键释放:停止发送重复码
实现思路
[*]外部中断捕获红外信号下降沿
[*]定时器测量脉冲宽度区分引导码/重复码
[*]状态机管理按键状态(短按/长按)
[*]连发加速功能(首次延迟后加速)#include <STC8H.H>
#include <intrins.h>

// 红外接收引脚配置
sbit IR_PIN = P3^2;// 假设使用INT0中断(P3.2)

// 全局变量
bit ir_flag = 0;   // 红外数据就绪标志
unsigned char ir_data; // 存储用户码、用户反码、键码、键反码
unsigned char repeat_count = 0;// 重复码计数器
unsigned long last_repeat_time = 0; // 上次重复时间戳
unsigned char key_hold = 0;      // 当前长按键值

// 定时器0初始化(1ms计时)
void Timer0_Init(void) {
    AUXR |= 0x80;   // 1T模式
    TMOD &= 0xF0;   // 模式0(16位自动重载)
    TL0 = 0xCD;   // 初始化值
    TH0 = 0xD4;
    TR0 = 1;      // 启动定时器
    ET0 = 1;      // 允许中断
    EA = 1;
}

// 外部中断0初始化
void INT0_Init(void) {
    IT0 = 1;      // 下降沿触发
    EX0 = 1;      // 允许中断
    EA = 1;
}

// 处理红外数据
void ProcessIR(unsigned char key) {
    static unsigned long last_key_time = 0;
    static unsigned char repeat_delay = 500; // 首次连发延迟500ms
    static unsigned char repeat_speed = 200; // 连发速度200ms
   
    if(key_hold != key) { // 新按键
      key_hold = key;
      // 执行短按操作
      if(key == 0x45) { // 假设0x45是音量+
            // 执行加操作
      }
      repeat_count = 0;
    } else { // 长按状态
      unsigned long now = (TH0 << 8 | TL0) + (unsigned long)TF0 * 65536;
      if(now - last_key_time > (repeat_count ? repeat_speed : repeat_delay)) {
            // 执行连发操作
            repeat_count++;
            last_key_time = now;
            // 加速逻辑(可选)
            if(repeat_count > 10) repeat_speed = 100;
            else if(repeat_count > 5) repeat_speed = 150;
      }
    }
}

// 外部中断0服务函数
void INT0_ISR(void) interrupt 0 {
    static unsigned int time_cnt;
    static unsigned char bit_cnt;
    static unsigned char data_cnt;
   
    time_cnt = 0;
    while(!IR_PIN); // 等待高电平
   
    // 测量9ms引导码
    while(IR_PIN) {
      time_cnt++;
      _nop_();_nop_();_nop_(); // 约10us延时
      if(time_cnt > 1000) break; // 超时退出
    }
   
    if(time_cnt > 900 && time_cnt < 1100) { // 9ms引导码
      // 接收数据帧...
    }
    else if(time_cnt > 4000 && time_cnt < 5000) { // 4.5ms重复码
      key_hold = ir_data; // 保存键值
      ir_flag = 2; // 重复码标志
    }
}

// 主函数
void main(void) {
    Timer0_Init();
    INT0_Init();
   
    while(1) {
      if(ir_flag) {
            if(ir_flag == 1) { // 首次按键
                // 处理键值ir_data
                ir_flag = 0;
            } else if(ir_flag == 2) { // 重复码
                ProcessIR(ir_data);
                ir_flag = 0;
            }
      }
      
      // 检测按键释放(1秒无重复码认为释放)
      if(key_hold && (GetCurrentTime() - last_repeat_time > 1000)) {
            key_hold = 0;
            repeat_count = 0;
      }
    }
}


Tank2535 发表于 2025-3-11 21:01:16

王昱顺 发表于 2025-3-11 20:01
连按不影响长按识别,只有检测到重复码才开始200ms(或者其他长度,需要长一点)的计时,计时到了再进行 ...

这应该是物理按键的思路,遥控的不一样。或许是我没想明白?

王昱顺 发表于 2025-3-11 21:04:34

Tank2535 发表于 2025-3-11 21:01
这应该是物理按键的思路,遥控的不一样。或许是我没想明白?

物理按键和这种数据方式传来的按键,从底层来看不都是处理按键按下的过程嘛,其实是一样的
将数据方式重新转换为按键的几个特征点,然后通过时间长度来识别就行了
页: [1]
查看完整版本: 关于NEC遥控器重复码的识别