/*******************************infrared************************************/
#include <reg52.h>
sbit IR_INPUT = P3^2; //紅外接收引腳
bit irflag = 0; //紅外接收標志,收到一幀正確數據后置1
unsigned char ircode[4]; //紅外代碼接收緩沖區
void InitInfrared()
{
IR_INPUT = 1; //釋放紅外引腳
TMOD &= 0X0F;
TMOD |= 0x10; //配置定時器1定時1模式
TR1 = 0;
ET0 = 0;
IT0 = 1; //外部 *下降沿* 產生外部中斷
EX0 = 1;
}
/*獲取當前高電平的持續時間*/
unsigned int GetHighTime()
{
TH1 = 0;
TL1 = 0;
TR1 = 1;
while(IR_INPUT) //當紅外引腳為1時,循環檢測等待,變為0時,
{ //則結束本循環
if(TH1 > 0x40) //當T1大于0x40即高電平持續時間超過約18ms時,強制退出循環,
{ //是為了避免信號異常是,程序假死在這里
break;
}
}
TR1 = 0;
return(TH1 * 256 + TL1);
}
/*獲取當前低電平的持續時間*/
unsigned int GetLowTime()
{
TH1 = 0;
TL1 = 0;
TR1 = 1;
while(!IR_INPUT)
{
if(TH1 > 0x40)
{
break;
}
}
TR1 = 0;
return(TH1 * 256 + TL1);
}
/*外部中斷INT1中斷服務程序,執行紅外接收及解碼*/
void EXINT0_ISR() interrupt 0
{
unsigned char i, j;
unsigned int time;
unsigned char byt;
time = GetLowTime(); //接收并判定引導碼的9ms低電平
if((time <7833) || (time > 8755)) //時間在8.5-9.5ms內,如果不在范圍內,關閉外部中斷,即關閉紅外接收,退出檢測
{
IE0 = 0;
return;
}
time = GetHighTime(); //接收并判定引導碼4.5ms
if((time<3686) || (time > 4608)) //如果接收高電平的時間不在4ms-5ms之間
{
IE0= 0; //關閉外部中斷,退出紅外檢測
return;
}
for(i=0; i<4; i++) //如果滿足上述引導碼電平時間要求,進入數據0,1判定
{
for(j=0; j<8; j++) //循環8次,獲取1 個字節
{
time = GetLowTime(); //獲取低電平時間
if((time<313) ||(time >718)) //判斷電平時間是否在340us-780之內,因為比特值0:560us+560us的空閑
{ //如果不滿足要求,退出外部中斷服務程序
IE0 = 0;
return;
}
time = GetHighTime(); //獲取高電平時間(空閑時間)
if((time>313) && (time <718)) //判斷空閑時間是否在340-780us之內,如果是的話,說明發送了1位 0
{
byt >>= 1; //先獲取位(0),
}
else if((time>1345) && (time<1751)) //如果在此獲取的空閑時間(高電平時間)在此范圍內,說明發送了1位 1
{
byt >>= 1; //獲取位1 操作
byt |= 0x80;
}
else //否則 既不是發送了0 也不是發送了 1 ,無效,退出外部中斷服務程序
{
IE0 = 0;
return;
}
}
ircode[i] = byt;
}
irflag = 1;
IE0 = 0;
}
/******************************************main*****************************************/
#include <reg52.h>
#include <intrins.h>
typedef unsigned char uchar;
typedef unsigned int uint;
sbit du=P2^6;
sbit we=P2^7;
uchar num,jianma1,jianma2;
unsigned char code dofly_DuanMa[]={ 0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
0x77, //"A"
0x7C, //"B"
0x39, //"C"
0x5E, //"D"
0x79, //"E"
0x71, //"F"
0x76, //"H"
0x38, //"L"
0x37, //"n"
0x3E, //"u"
0x73, //"P"
0x5C, //"o"
0x40, //"-"
0x00, //熄滅
0x00 //自定義
};// 顯示段碼值0~9
unsigned char T0RH = 0; //T0重載值的高字節
unsigned char T0RL = 0; //T0重載值的低字節
extern bit irflag;
extern unsigned char ircode[4];
extern void InitInfrared(void);
void ConfigTimer0(unsigned int ms);
void main()
{
EA = 1; //開總中斷,開始準備接受紅外信號
InitInfrared(); //初始化紅外功能
ConfigTimer0(1); //配置T0定時1ms
PT0 = 1; //配置T0中斷為高優先級,啟用本行可消除接收時的閃爍
while (1)
{
if (irflag) //紅外接收標志位,1表示接受完畢,
{
irflag = 0;
/* switch(ircode[2])
{
case 0x0c:num=dofly_DuanMa[1];break;//1 顯示相應的按鍵值
case 0x18:num=dofly_DuanMa[2];break;//2
case 0x5e:num=dofly_DuanMa[3];break;//3
case 0x08:num=dofly_DuanMa[4];break;//4
case 0x1c:num=dofly_DuanMa[5];break;//5
case 0x5a:num=dofly_DuanMa[6];break;//6
case 0x42:num=dofly_DuanMa[7];break;//7
case 0x52:num=dofly_DuanMa[8];break;//8
case 0x4a:num=dofly_DuanMa[9];break;//9
default :break;
} */
jianma1=dofly_DuanMa[ircode[2] >> 4];
jianma2=dofly_DuanMa[ircode[2]&0x0f];
}
}
}
/* 配置并啟動T0,ms-T0定時時間 */
void ConfigTimer0(unsigned int ms)
{
unsigned long tmp; //臨時變量
tmp = 11059200 / 12; //定時器計數頻率
tmp = (tmp * ms) / 1000; //計算所需的計數值
tmp = 65536 - tmp; //計算定時器重載值
tmp = tmp + 18; //補償中斷響應延時造成的誤差
T0RH = (unsigned char)(tmp>>8); //定時器重載值拆分為高低字節
T0RL = (unsigned char)tmp;
TMOD &= 0xF0; //清零T0的控制位
TMOD |= 0x01; //配置T0為模式1
TH0 = T0RH; //加載T0重載值
TL0 = T0RL;
ET0 = 1; //使能T0中斷
TR0 = 1; //啟動T0
}
/* 數碼管動態掃描刷新函數,需在定時中斷中調用 */
void LedScan()
{
/* du=1;
P0=num;
du=0;
P0=0xff;
we=1;
P0=0xfe;
we=0; */
du=1;
P0=jianma1;
du=0;
P0=0xff;
we=1;
P0=0xbf;
we=0;
_nop_();
du=1;
P0=jianma2;
du=0;
P0=0xff;
we=1;
P0=0x7f;
we=0;
_nop_();
}
/* T0中斷服務函數,執行數碼管掃描顯示 */
void InterruptTimer0() interrupt 1
{
TH0 = T0RH; //重新加載重載值
TL0 = T0RL;
LedScan(); //數碼管掃描顯示
}
功能:講遙控器鍵碼顯示在數碼管的第7,8位。 問題:第7位數碼管,顯示不清楚,只是個殘影,第八位數碼管顯示正常,無論我怎么減小延遲函數(最后用_nop_)也無法解決這個現象,求高手 幫我看看。謝謝了
|