我做了一个音源切换的装置,有遥控和按键功能,现在遇到一个问题是,遥控不是很灵光,有时很灵,有时要按两三下才有,下列是我写的程序,对于遥控方面,各位有什么建议和好的方法.
我的方法是,采用外部下降沿(因为接收头之后反相)中断,一进入中断开启16位定时器1,开始计时,直到下一个下降沿到来,从而计到脉冲的时间,读码.
/****************************************************** 音源切换装置 12M晶振, 定时器计时一次1us. ******************************************************/ #include "STC12C2052AD.h" #include "intrins.h"
#define channel_0 0xf7 #define channel_1 0xfb #define channel_2 0xfd #define channel_3 0xfe
#define LED_channel_0 CH_0_LED=0;CH_1_LED=1;CH_2_LED=1;CH_3_LED=1; #define LED_channel_1 CH_0_LED=1;CH_1_LED=0;CH_2_LED=1;CH_3_LED=1; #define LED_channel_2 CH_0_LED=1;CH_1_LED=1;CH_2_LED=0;CH_3_LED=1; #define LED_channel_3 CH_0_LED=1;CH_1_LED=1;CH_2_LED=1;CH_3_LED=0;
sbit CH_0_LED=P1^4; sbit CH_1_LED=P1^5; sbit CH_2_LED=P1^6; sbit CH_3_LED=P1^7; sbit CD4052_A=P3^4; sbit CD4052_B=P3^5;
unsigned char key_old,key_temp; unsigned int key_delay=0; bit key_ok,remote_ok;
unsigned int p_width; bit pulse_1; unsigned char remote_count,remote_temp,user_code,level;
void T1_initial(void); void Port_initial(void); void key_scan(void); void key_action(void); void delay_10us(unsigned int t); void remote_action(void);
void INT1_ISR(void) interrupt 2 //下降沿中断 { CH_3_LED=!CH_3_LED; if (TR1==0) { TH1=0; TL1=0; TR1=1; //启动计数 } else { TR1=0;//停止计数 p_width=TH1; p_width= (p_width<<8)+TL1; if(p_width>= 5000 && p_width <=40000) //13000->0x32c8,14000->0x368b 如果开始引导码有效。 { pulse_1=1; TH1=0; TL1=0; TR1=1; //开始计数。 } else { if (pulse_1==1) //如果引导码有效,则开始接收用户码和数据码 { if (p_width>=200 && p_width<=4550)//如果码有效,1000->0x03e8,2250->0x08ca { if (p_width<=1400) level=0; if (p_width>=1400) level=1; remote_count++; if (remote_count > 16) //用户码丢弃。只保存键码。 { user_code= (user_code<<1)+level; } if (remote_count==24) {remote_ok=1;remote_count=0;pulse_1=0;TR1=0;} //如果已经收到32个用户码和数据码,则重新开始检测遥控。 TH1=0; TL1=0; TR1=1; //开始计数。 }
else //码无效,则退出。 { pulse_1=0; remote_ok=0; remote_count=0; TH1=0; TL1=0; TR1=0; //关闭定时器,重新开始下一个轮回。 } } else {TH1=0;TL1=0;} } }
} /*===================================================*/ void main(void) { Port_initial(); T1_initial(); LED_channel_3; EA=1; while (1) { key_scan(); remote_action(); key_action(); //delay_10us(1); //1ms 100 }
}
/*********************************************************** Timer1初始化,测量脉宽 ***********************************************************/ void T1_initial(void) { TMOD=0X10; //Timer1工作在模式1方式。 16位定时器 TCON=0x04; //开启外部中断1,并且选用下降沿触发。 TH1=0; TL1=0; EX1=1; //TR1=0;//未开启定时器 }
/************************************************************ PORT端口初始化 ***********************************************************/ void Port_initial(void) { P1M0=0X00;//全部为标准I/O口 P1M1=0X00; P3M0=0x00; //P3。3设为输入。 P3M1=0x00; P1=0XFF; P3=0Xff; } /*********************************************************** key_scan(); ***********************************************************/ void key_scan(void) { if ((P1|0xf0)!=0xff) //有键 { key_temp=P1|0xf0; if (key_temp==key_old) { key_delay++; } else key_old=key_temp; } else { if (key_delay >=60) { key_ok=1; key_delay=0; // return key_temp;//返回键值 } } }
/*********************************************************** key_action(); ***********************************************************/ void key_action(void) { unsigned char temp; if (key_ok) { temp=key_temp; goto action;} if (remote_ok) { temp=remote_temp;} action: switch (temp) { case channel_0: LED_channel_0;//执行按键功能1 CD4052_A=0; CD4052_B=0; key_ok=0; remote_ok=0; temp=0; break; case channel_1: LED_channel_1;//执行按键功能2 CD4052_A=1; CD4052_B=0; key_ok=0; remote_ok=0; temp=0; break; case channel_2: LED_channel_2;//执行按键功能3 CD4052_A=0; CD4052_B=1; key_ok=0; remote_ok=0; temp=0; break; case channel_3: LED_channel_3;//执行按键功能4 CD4052_A=1; CD4052_B=1; key_ok=0; remote_ok=0; temp=0; break; default:break; } } /********************************************************* remote_action。 *********************************************************/ void remote_action(void) { if (remote_ok) { switch (user_code) { case 0x50: remote_temp=channel_0;user_code=0;break; case 0xc8: remote_temp=channel_1;user_code=0;break; case 0x68: remote_temp=channel_2;user_code=0;break; //case 0x50af: remote_temp=channel_3;break; default:break; }
} }
/********************************************************* 普通延时 *********************************************************/ void delay_10us(unsigned int t) { unsigned char j; for(;t>0;t--) for(j=25;j>0;j--) ; }
|