本keil c51程序适用uPC1621/uPC1622及兼容的红外遥控器芯片,占用外部中断0和定时器1,以中断方式解码,节省系统资源,以查询方式检测遥控信号是否有效.
解码思路:
红外线经一体化接受头解码放到后送到单片机的外部中断0,单片机设置外部中断下降沿触发,T0和T1为16位定时器,T0在系统启动后定时5ms.T1在外部中断0启动后开始定时,初值为0,每次在INT0中断后先读T1计数值,并重设初值为0,而且判断T1的计数值,
- //Fosc=11.0592MHz
- // states for and variables IR data processing ;
- typedef enum
- {
- IR_idle,
- IR_waitstart,
- IR_getaddr,
- IR_getaddrinv,
- IR_getdata,
- IR_getdatainv
- }_IRstate;
- _IRstate IRstate = IR_idle;
- unsigned char IRaddr=0xff;
- unsigned char _IRaddr=0xff;
- unsigned char IRdata=0xff;
- unsigned char _IRdata=0xff;
- unsigned char IR_repeat=0;
- unsigned char IR_ready=0;
- unsigned char IR_poweron=0;
- //bit ir_done=0;
- // time constants
- unsigned int IRtimer=0; // IR timeout
- //cpu初始化
- void cpu_init(void)
- {
- TMOD=0X11; // T0 and T1 十六位定时
- TH0=0xee; //fosc=11.0592M,timer=5ms
- TL0=0x00;
- TR0=1; // run timer 0;
- TF0=0;
- ET0=1; // enable tmr 0 overflow interrupt
- IT0=1; // int0 edge sensitive
- EX0=1; // enable "int0"
- EA=1; // global interupt enable
- }
- //T0中断
- void tmrint() interrupt 1
- {
- TH0=0xee;
- TL0=0x00;
- if (IRtimer) //IR接收超时
- --IRtimer; //
- else
- {
- IRstate=IR_idle;
- // IR_poweron=0;
- }
- }
- //Fosc=11.0592MHz
- #define msec_12p5 0x2d00
- #define msec_15 0x3600
- #define msec_9 0x2066
- //#define msec_9 0x1066
- #define msec_2p5 0x900
- #define msec_0p9 0x33d
- #define msec_1p68 0x610
- //void IRint() interrupt 0(void)
- //When the IR receive pin goes low and interrupt is generated
- // IR is collected by starting timer 2 in the first falling edge of the pin
- // then on every other falling edge, the timer value is saved and the timer restarted .
- // the captured time is then used to get the IR data
- // a "start of data" is 13.5Msec,a "1" is 2.25Msec,a "0" is 1.12 msec and a "repeat" is 11.25msec.
- // the counter increments at 1.085 Usec
- // I allow a fairly large tolerance to time jitter but there are no false triggers seen.
- void IRint() interrupt 0
- {
- static unsigned char bits;
- unsigned short time;
- switch(IRstate)
- {
- case IR_idle:
- TL1=0;
- TH1=0;
- TR1=1;
- IRstate=IR_waitstart;
- IRtimer=26;
- break;
- case IR_waitstart: //P2_4=!P2_4;
- TR1=0;
- time=TH1;
- time =(time <<8)+TL1;;
- TL1=0;
- TH1=0;
- TR1=1;
- if ((time > msec_12p5)&&(time < msec_15)) // greater than 12.5Msec & less than 15 msec = start code
- {
- IRaddr=0;
- _IRaddr=0;
- IRdata=0;
- _IRdata=0;
- bits=1;
- IRstate=IR_getaddr;
- }
- else if ((time > msec_9)&&(time < msec_12p5))// less than 12.5Msec and greater than 9 msec =Repeat code
- {
- IR_repeat=2;
- IRstate=IR_idle;
- }
- else
- { // to short, bad data just go to idle
- IRstate=IR_idle;
- }
- break;
- case IR_getaddr: // P2_4=!P2_4;
- TR1=0;
- time=TH1;
- time =(time <<8)+TL1;;
- TL1=0;
- TH1=0;
- TR1=1;
- if ((time>msec_2p5)||(time<msec_0p9))// if > 2.5msec or shorter than .9Msec bad data , go to idle
- {
- IRstate=IR_idle;
- break;
- }
- if (time>msec_1p68)// greater than 1.68Msec is a 1
- {
- IRaddr|= bits;
- }
- bits=bits<<1;
- if (!bits)
- {
- IRstate=IR_getaddrinv;
- bits=1;
- }
- break;
- case IR_getaddrinv: //P2_4=!P2_4;
- TR1=0;
- time=TH1;
- time =(time <<8)+TL1;;
- TL1=0;
- TH1=0;
- TR1=1;
- if ((time>msec_2p5)||(time<msec_0p9))// if > 2.5msec or shorter than .9Msec bad data , go to idle
- {
- IRstate=IR_idle;
- break;
- }
- if (time>msec_1p68)// greater than 1.68Msec is a 1
- {
- _IRaddr|= bits;
- }
- bits=bits<<1;
- if (!bits)
- {
- IRstate=IR_getdata;;
- bits=1;
- }
- break;
- case IR_getdata:
- TR1=0;
- time=TH1;
- time =(time <<8)+TL1;;
- TL1=0;
- TH1=0;
- TR1=1;
- if ((time>msec_2p5)||(time<msec_0p9))// if > 2.5msec or shorter than .9Msec bad data , go to idle
- {
- IRstate=IR_idle;
- break;
- }
- if (time>msec_1p68)// greater than 1.68Msec is a 1
- {
- IRdata|= bits;
- }
- bits=bits<<1;
- if (!bits)
- {
- IRstate=IR_getdatainv;
- bits=1;
- }
- break;
- case IR_getdatainv:
- TR1=0;
- time=TH1;
- time =(time <<8)+TL1;;
- TL1=0;
- TH1=0;
- TR1=1;
- if ((time>msec_2p5)||(time<msec_0p9)) // if > 2.5msec or shorter than .9Msec bad data , go to idle
- {
- IRstate=IR_idle;
- break;
- }
- if (time>msec_1p68)// greater than 1.68Msec is a 1
- {
- _IRdata|= bits;
- }
- bits=bits<<1;
- if (!bits) // we have it all , now we make sure it is a NEC code from the CHS IR transmitter
- { // make sure address,~address are correct , data ,~data are correct and address is 0.
- IR_ready=((IRaddr^_IRaddr)==0xff)&&((IRdata^_IRdata)==0xff)&&(IRaddr==0);
- if(IR_ready)
- {
- IRstate=IR_idle;
- }
- }
- break;
- default:
- IRstate=IR_idle;
- break;
- }
- }
- void main(void)
- {
- cpu_init();
- while(1)
- {
- if(IR_ready)
- {
- IR_ready=0;
- switch(IRdata)
- {
- case 0x45: //1
- //your code
- break;
- case 0x44: //3
- //your code
- break;
- case 0x43: //4
- //your code
- break;
- case 0x08: //prev
- //your code
- break;
- case 0x5a: //next
- //your code
- break;
- default:
- break;
- }
- }
- }
- }