关于NEC遥控器重复码的识别
各位兄弟,请教一下NEC遥控器重复码的识别。也就是长按是如何实现的?做了很多用到遥控器类的产品,一直没有用到长按功能,现在有客户提出来用长按实现连加、连减。我试着读取2.25ms的重复码,可以正常读取,但是不能实现长按功能,汗!有例程的兄弟不吝赐教!谢谢!保存一下最后一个键值码,,如果读取到是重复码就把上一次的键值码发送给应用层 _奶咖君_ 发表于 2025-3-11 17:50
保存一下最后一个键值码,,如果读取到是重复码就把上一次的键值码发送给应用层 ...
键值码,短按的时候也是必须保存的。 Tank2535 发表于 2025-3-11 18:46
键值码,短按的时候也是必须保存的。
做一个连续检测长度判断,每隔一段时间,例如200ms,判断当前是否还有新接收的键值码。
如果还有的话就判断是否跟上次连续一致,等待多次连续后(例如三次重复)就开始以固定间隔连续改变需要设置的变量(例如数值的连续自加)。
如果判断跟上次不一样,就重新开始200ms计时并清除重复计数 王昱顺 发表于 2025-3-11 18:57
做一个连续检测长度判断,每隔一段时间,例如200ms,判断当前是否还有新接收的键值码。
如果还有的话就判 ...
这样也行?32位码,如果连按就出错了 Tank2535 发表于 2025-3-11 19:52
这样也行?32位码,如果连按就出错了
连按不影响长按识别,只有检测到重复码才开始200ms(或者其他长度,需要长一点)的计时,计时到了再进行重复判别
如果按下了其他按键,可以直接清空计时,这样只有在长按的时候才有连加反应
具体效果应该是按下+按键,立刻加1,等待识别到重复码超过指定时间长度(长按了一会)然后再开始连续自加 以下内容来自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;
}
}
}
王昱顺 发表于 2025-3-11 20:01
连按不影响长按识别,只有检测到重复码才开始200ms(或者其他长度,需要长一点)的计时,计时到了再进行 ...
这应该是物理按键的思路,遥控的不一样。或许是我没想明白? Tank2535 发表于 2025-3-11 21:01
这应该是物理按键的思路,遥控的不一样。或许是我没想明白?
物理按键和这种数据方式传来的按键,从底层来看不都是处理按键按下的过程嘛,其实是一样的
将数据方式重新转换为按键的几个特征点,然后通过时间长度来识别就行了
页:
[1]