#include "config.h"
/***********************
infrared.c文件程序源代碼
*************************/
#include <reg51.h>
sbit IR_INPUT = P1^0; //紅外接收引腳
bit irflag = 0; //紅外接收標志,收到一幀正確數據后置1
unsigned char ircode[4]; //紅外代碼接收緩沖區
void InitInfrared(void) //紅外功能的初始化函數
{
TMOD &= 0x0F; //清零T1的控制位
TMOD |= 0x10; //配置T1為模式1
TR1 = 0; //停止T1計數
ET1 = 0; //禁止T1中斷
IT1 = 1; //設置INT1為負邊沿觸發
EX1 = 1; //使能INT1中斷
}
unsigned int GetHighTime(void) //獲取高電平時間
{
TH1 = 0; //清零T1計數初值
TL1 = 0;
TR1 = 1; //啟動T1計數
while (IR_INPUT) //紅外輸入引腳為1時循環檢測等待,變為0時則結束本循環
{
if (TH1 >= 0x40)
{ //當T1計數值大于0x4000,即高電平持續時間超過約18ms時,
break; //強制退出循環,是為了避免信號異常時,程序假死在這里。
}
}
TR1 = 0; //停止T1計數
return (TH1*256 + TL1); //返回T1的計數值
}
unsigned int GetLowTime(void) //獲取低電平時間
{
TH1 = 0; //清零T1計數初值
TL1 = 0;
TR1 = 1; //啟動T1計數
while (!IR_INPUT) //紅外輸入引腳為0時循環檢測等待,變為1時則結束本循環
{
if (TH1 >= 0x40)
{ //當T1計數值大于0x4000,即低電平持續時間超過約18ms時,
break; //強制退出循環,是為了避免信號異常時,程序假死在這里。
}
}
TR1 = 0; //停止T1計數
return (TH1*256 + TL1); //返回T1的計數值
}
void EXINT1_ISR() interrupt 2 //INT1中斷服務函數,執行紅外接收及解碼
{
unsigned char i, j;
unsigned char byt;
unsigned int time;
//接收并判定引導碼的9ms低電平
time = GetLowTime();
if ((time<7833) || (time>8755)) //時間判定范圍為8.5~9.5ms,
{ //超過此范圍則說明為誤碼,直接退出
IE1 = 0; //退出前清零INT1中斷標志
return;
}
//接收并判定引導碼的4.5ms高電平
time = GetHighTime();
if ((time<3686) || (time>4608)) //時間判定范圍為4.0~5.0ms,
{ //超過此范圍則說明為誤碼,直接退出
IE1 = 0;
return;
}
//接收并判定后續的4字節數據
for (i=0; i<4; i++) //循環接收4個字節
{
for (j=0; j<8; j++) //循環接收判定每字節的8個bit
{
//接收判定每bit的560us低電平
time = GetLowTime();
if ((time<313) || (time>718)) //時間判定范圍為340~780us,
{ //超過此范圍則說明為誤碼,直接退出
IE1 = 0;
return;
}
//接收每bit高電平時間,判定該bit的值
time = GetHighTime();
if ((time>313) && (time<718)) //時間判定范圍為340~780us,
{ //在此范圍內說明該bit值為0
byt >>= 1; //因低位在先,所以數據左移,高位為0
}
else if ((time>1345) && (time<1751)) //時間判定范圍為1460~1900us,
{ //在此范圍內說明該bit值為1
byt >>= 1; //因低位在先,所以數據左移,
byt |= 0x80; //高位置1
}
else //不在上述范圍內則說明為誤碼,直接退出
{
IE1 = 0;
return;
}
}
ircode[ i] = byt; //接收完一個字節后保存到緩沖區
}
irflag = 1; //接收完畢后設置標志
IE1 = 0; //退出前清零INT1中斷標志
}
|