📄 irrexample.c
字号:
/////////////////////////////
以下程序是用扫描方法读取红外遥控器波形
若有条件(如使用AVR),可以使用捕获脉宽中断,更容易编程
//////////////////////////
//T1计数值,区分红外传输的位值.1个计数=2us(Fosc=4MHz)
#define IRR_DECODE_DELAY 120 //解码延时限制,单位ms
#define IRR_H_DELAY 8 //高电平延时限制,单位ms
#define IRR_L_DELAY 5 //低电平延时限制,单位ms
#define IRR_HEAD_MINTIME 1950 //2250-300 //4500us, 300us为估计2次扫描之间最大延时
#define IRR_HEAD_MAXTIME 2550 //2250+300
#define IRR_0_MAXTIME 430 //280+150 //560us
#define IRR_0_MINTIME 130 //280-150
#define IRR_1_MAXTIME 1000 //850+150 //1700us
#define IRR_1_MINTIME 700 //850-150
/*********读取红外接收值IRR********/
//PA7
//TL1838B一体化红外接收管:无接收,输出H,接收到38kHz载波输出L. 2套信号之间要求隔开25ms以上
//输出:非零表示H,0表示L
unsigned char read_IRR(void)
{
return PINA&0x80; //PA7
}
/***********扫描红外遥控器按键输入IRR:PC2 解码子程序***************
1)遥控器以upd6121G或HT6221为主控芯片遥控器
2)发出的信号电平变化最小间隔为0.56ms.必须保证在0.56ms内程序能够至少扫描1次!
3)位定义:测量接收波形中高电平的脉宽:4.5ms为引导码(起始),0: 0.56ms,1: 1.7ms
4)一次键码共4Byte 32位:地址码+地址码反码+键码+键码反码; LSB(D0)先出
5)扫描的结果会把键值放在IRRkey
******注意2次扫描之间间隔应该远小于0.56ms!!!
*/
void scan_IRR_decode(void)
{unsigned char i;
unsigned int tempt;
//不断读取1路IRR,获取波形信息
newIRR=read_IRR();
if((!oldIRR)&&(newIRR)) //上升沿
{delay_IRR_L=0; //关闭低电平延时计时
delay_IRR_H=1; //开始高电平延时计时
//oldTCNT1=TIM16_ReadTCNT1(); //开始对高电平计时
TIM16_WriteTCNT1(0); //清零TIMER1,开始对高电平计时(可以节省运算减法的时间)
}
else if((oldIRR)&&(!newIRR)) //下降沿
{delay_IRR_L=1; //开始低电平延时计时
delay_IRR_H=0; //关闭高电平延时计时
//计算此段低电平时间差
/*tempt=TIM16_ReadTCNT1();
if (tempt>oldTCNT1) IRRtime=tempt-oldTCNT1;
else IRRtime=0xffff-oldTCNT1+tempt+1;*/
IRRtime=TIM16_ReadTCNT1();
//判断收到的位信息
if ((IRRtime>IRR_HEAD_MINTIME)||(IRRtime<IRR_0_MINTIME))
{//IRRbyte=0; //收到长高电平(引导码,4.5ms)或是干扰,复位
IRRbit_prt=0; //位指针清零
}
else //有效数据位
{
if (IRRtime<IRR_0_MAXTIME) IRRbit[IRRbit_prt]=0; //收到0
else if (IRRtime>IRR_1_MINTIME) IRRbit[IRRbit_prt]=0xff; //收到1
else IRRbit[IRRbit_prt]=2; //错码
IRRbit_prt++;
if (IRRbit_prt==32) //已收满32位,取键值
{IRRkey=judge_IRRkey();
//IRRbit_prt=0;
}
}
}
oldIRR=newIRR;
}
//已收满32位,判断键值
//无效键值:NOKEY=0xff
unsigned char judge_IRRkey(void)
{ unsigned char i,j;
//先判断反码
j=0;
for(i=0;i<8;i++)
{if (IRRbit[i+8]!=(~IRRbit[i]))
{j=1;
break;
}
if (IRRbit[i+24]!=(~IRRbit[i+16]))
{j=1;
break;
}
}
if(j) return NOKEY; //解码错误
//判断地址码是否正确
j=0;
for(i=0;i<8;i++)
{if(IRRbit[i]) j|=(1<<i); //低位先收
}
if (j!=IRR_CUSTOMCODE) return NOKEY; //地址码错误
//返回键值
j=0;
for(i=16;i<24;i++)
{if(IRRbit[i]) j|=(1<<(i-16));
}
return j;
}
//扫描红外遥控器按键输入
//先扫描红外遥控器按键输入引导区: 低电平持续9ms
//只有探测到下降沿,且低电平>IRR_L_DELAY(5ms),即可能出现引导码,才进入扫描键盘子程序
void scan_IRRkey(void)
{
IRRkey=NOKEY; //上次扫描获得的键值不保留,需马上利用
//不断读取1路IRR,获取波形信息
newIRR=read_IRR();
if((oldIRR)&&(!newIRR)) //下降沿
{delay_IRR_L=1; //开始低电平延时计时
}
else if(newIRR) delay_IRR_L=0; //关闭低电平延时计时
if (delay_IRR_L>IRR_L_DELAY) //可能进入引导区,开始连续扫描键盘
{delay_IRR_L=1; //开始低电平延时计时
delay_IRR_H=1; //开始高电平延时计时
delay_IRR_decode=1; //开始解码延时计时
IRRbit_prt=0;
//开始解码
//若低电平或高电平持续时间过长,或者解码时间超出108ms,退出解码程序
while((delay_IRR_L<=(IRR_L_DELAY*3))&&(delay_IRR_H<=IRR_H_DELAY)&&(delay_IRR_decode<=IRR_DECODE_DELAY)&&(IRRbit_prt<32))
{scan_IRR_decode(); //解码后才获得键值IRRkey
}
delay_IRR_L=0; //关闭低电平延时计时
delay_IRR_H=0; //关闭高电平延时计时
delay_IRR_decode=0; //关闭解码延时计时
}
oldIRR=newIRR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -