好久没折腾过单片机的东西了,最近在折腾着自己DIY一个APE播放机,要用到红外控制,复习了下51的东西,用AT89C2051写了个红外解码程序,丢在这里吧,供以后参考; #ifndef _IR_H #define _IR_H #define ST_FREE 0X01 #define ST_TRIGGED 0x02 #define ST_CODE 0x03 #define LEN_HIGH 0x15//0.1*16=1.60ms 0.56+1.68=2.24ms #define LEN_FINISH 300//20ms/0.1=200 #define IR_COUNT_END 0x20//16地址+8位数据+8位数据反码 void init_int(); // 中断初始化函数,是能EX0和ET0 void init_timer_com(); // timer和UART初始化函数 void send_com(unsigned char data_send);//串口数据发送函数 void int_enable(unsigned char flag); //中断开关函数 unsigned char get_ir_rawcode(); //取得原始红外码 #endif #include <at892051.h> #include "ir.h" int m_sys_tick,m_tick_cur; //系统时钟TICK和当前TICK unsigned char s_ir; //系统状态机 unsigned char ir_mask[16],count_ir; //可以容纳最多128位数据 //以上变量都需要在初始化时做清零 /* × | ST_FREE | ST_TRIGGED | ST_FREE * * |-------------|-引导码-|-地址码-|-数据码-|-停止码-|-----------------------| * */ void func_intex0() interrupt 0 { unsigned char i,j; if(s_ir==ST_FREE)//引导码,进入TRIG状态,建立好同步时机,不做记录,后面码字刚好4个字节 { s_ir=ST_TRIGGED; m_tick_cur=m_sys_tick; } else if(s_ir==ST_TRIGGED) { s_ir=ST_CODE; m_tick_cur=m_sys_tick; count_ir=0; } else { i=count_ir/8; j=count_ir%8; if((m_sys_tick-m_tick_cur)>LEN_HIGH) { ir_mask[i]|=0x01<<j; } else { ir_mask[i]&=~(0x01<<j); } m_tick_cur=m_sys_tick; count_ir++; } } void func_intt0() interrupt 1 { m_sys_tick++; } void main() { unsigned char data_ir; s_ir=ST_FREE; m_sys_tick=m_tick_cur=0; count_ir=0; P3=0XFF; P1=0XFF; init_int(); init_timer_com(); int_enable(1); while(1) { if((s_ir==ST_CODE)&&(m_sys_tick-m_tick_cur)>LEN_FINISH)//已经超过20MS没有收到红外信号 { if(count_ir>=IR_COUNT_END)//如果是完整的码字,处理并发送 { data_ir=get_ir_rawcode(); send_com(data_ir); P1=data_ir; } else//如果非完整码字或重复码,直接丢弃,进入FREE状 { send_com(0xff); } s_ir=ST_FREE; // 一段码已经接受完成,设置为空闲状态 } } } void init_int() { IE=0;//先清整个寄存器,关闭总中断 IP=0;//关闭优先级管理 IT0=1;//外部中断0下降沿触发 ET0=1;//定时器0开中断 EX0=1;//外部中断0开中断 } void int_enable(unsigned char flag) { if(flag) { EA=1; } else { EA=0; } } void init_timer_com() { TMOD=0x22;//都为模式2 定时,自动加载初始值 TH0=TL0=0X9c;//100us TH1=TL1=0xE6;//1200 band/s SCON=0X00;//先清零 PCON=0X00;//不使用倍速功能 SM0=0; SM1=1;//使用模式1,8位异步收发,不允许接受 TR0=TR1=1;//打开定时器,初始化完成 } void send_com(unsigned char data_send) { SBUF=data_send; while(!TI); TI=0; } unsigned char get_ir_rawcode() { if(ir_mask[2]==~ir_mask[3]) { return ir_mask[2]; } else { return 0xff; } }