去年由于工作的需要在炬力的ATJ2091MP3方案上增加红外遥控,下面简单介绍一下方法.解码的是NEC协议的红外遥控,NEC协议是最广泛的红外遥控手段,要对NEC红外遥控器进行解码,首先我们要知道红外遥控的原理和NEC协议。
1.红外遥控器主要有发射和接收两部份,发射部分由盘矩阵、编码调制、红外发送器;
接收部分包括光、电转换放大器、解调、解码电路,现在都是用一体化红外线接收器了。
NEC协议 红外遥控32位二进制码是串行脉宽调制的,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合
表示“1”,其波形如下。
2.接收解码:
首先只少要有一个定时器和一个普通的IO口,由炬力的ATJ2091 MP3定时器已做其他作用,只能用CTC做定时器.将定时器设定中断时间有100us(可以设置其他值但最好<100us),I设置IO口为输入。
每次定时器中断扫描IO口,看IO口是否为低电平,用低电平时间的长短表示0(565us)或者1(1900us),低电平进行中断记数器记数,当IO口为高电平时停止记数,判断是不是有效电平(引导码时间为4.5ms大于设置的有效时间为出错时间记数器清0)。设低电平时间大于200us,小于1.9ms即2 < Int_Counter < 19为有效电平。接下来就是断低电平时间是0还是1,设2 < Int_Counter < 10为0;10 < Int_Counter < 19为1..程序主要利用Int_Counter移位累加器A减去10,然后通过借位标志位C是否为1为判断码值是1还是0,但收到的值是反码.下面是具体实现的例程:仅供参考.
Int_Counter defb 0x00 //中断记数器
IR_code_num defb 0x00 //码值记数器
IR_Data_Buffer0 defb 0x00 //遥控码暂存器0
IR_Data_Buffer1 defb 0x00 //遥控码暂存器1
IR_Data_Buffer2 defb 0x00 //遥控码暂存器2
IR_Data_Buffer3 defb 0x00 //遥控码暂存器3
//************************************************************
/*
** : KeyInt
** PURPOSE: Keyboard interrupt
** PARAMETERS: none
** DEION:
*/
//************************************************************
KeyInt:
/*-------------------------- */
/***********************/
CTC定时器重装代码
...................
/**********************/
in a,(0xf2) //读IO状态
bit 2,a
jr z,IR_KEY_SCAN //高电平结束中断记数器记数进行电平有效判断.
ld a,(Int_Counter)
inc a //低电平中断记数器记数加一
ld (Int_Counter),a
cp 0x50 //中断记数器记数大于一定值小于9mS出错进入IR_code_err
jr c,IR_CT_Exit //退出中断子程序
jr IR_code_err
IR_KEY_SCAN: //有效电平判断.
/*--------------------------*/
ld a,(Int_Counter) //将中断记数器值移进累加器进行比较.
cp 0x02 //2*100us=200us
jr z,IR_CT_Exit //低电平小于200us无效电平退出大于有效
cp 0x13 //19*100us=1.9同ms
jr nc,IR_code_err //低电平大于1.9ms无效电平退出不于有效
sub 0x0a //将中断记数器即A里的值减去10, 0(0.2ms-1ms);1(1ms-1.9ms)
/*--------------------------*/
ld a,(IR_Data_Buffer0) //以下几条为红外遥控器值保存,利用上一条语句A-0x0a是否使进位标C置1区分遥控码是1还是0(这值为反码),然后将移到遥控码暂存器就可以得到32位遥控码值。
rra //A带进位循环右移1位(Z80命令)
ld (IR_Data_Buffer0),a
ld a,(IR_Data_Buffer1)
rra
ld (IR_Data_Buffer1),a
ld a,(IR_Data_Buffer2)
rra
ld (IR_Data_Buffer2),a
ld a,(IR_Data_Buffer3)
rra
ld (IR_Data_Buffer3),a
ld a,(IR_code_num) //码值记数器加一
inc a
ld (IR_code_num),a
CP 0x20 //码值记数器是否等于32
jr c, IR_CNT_CLR //不等于清除中断记数器退出
jr z ,IR_Key_Check //等于32就可以进行对码。
IR_code_err: //出错清除暂存器
ld a,00h
ld (IR_Data_Buffer0),a
ld (IR_Data_Buffer1),a
ld (IR_Data_Buffer2),a
ld (IR_Data_Buffer3),a
ld (IR_code_num),a
IR_CNT_CLR: //中断记数器清0
ld a,00h
ld (Int_Counter),a
IR_CT_Exit:
ret