在编写红外接收程序时,遵循了NEC协议,而其表示数据时,依靠高低电平空闲的不同表示0和1,需要获取接受高低电平时间进行判断。需要用到两个定时器,开发板上红外接收用到了中断0,则需要用定时器1数码管扫描.
**************main.c**************
#include <reg52.h>
#include <intrins.h>
typedef unsigned char u8;
typedef unsigned int u16;
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;
unsigned char code LedChar[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //数码管显示字符转换表
unsigned char LedBuff[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
u8 T1RH = 0;
u8 T1RL = 0;
extern bit irflag;
extern u8 ircode[4];
extern void InitInfrared();
void ConfigTimer0(u16 ms);
void main()
{
EA = 1;
InitInfrared();
ConfigTimer0(1);
PT1 = 1; //配置T0中断为高优先级,启用本行消除接收时的闪烁
while(1)
{
if(irflag)
{
irflag = 0;
LedBuff[5] = LedChar[ircode[0] >> 4];
LedBuff[4] = LedChar[ircode[0] & 0x0f];
LedBuff[1] = LedChar[ircode[2] >> 4];
LedBuff[0] = LedChar[ircode[2] & 0x0f];
}
}
}
/*配置T0*/
void ConfigTimer0(u16 ms)
{
unsigned long temp;
temp = 11059200 / 12;
temp = (temp * ms) / 1000;
temp = 65536 - temp;
temp = temp + 13;
T1RH = (u8)(temp >> 8);
T1RL = (u8)temp;
TMOD &= 0x0f;
TMOD |= 0x10;
TH1 = T1RH;
TL1 = T1RL;
ET1 = 1;
TR1 = 1;
}
void LedScan()
{
static u8 i = 0;
P0 = 0x00;
switch(i)
{
case 0SC = 0;LSB = 0;LSA = 0;i++0 = LedBuff[0];break;
case 1SC = 0;LSB = 0;LSA = 1;i++0 = LedBuff[1];break;
case 2SC = 0;LSB = 1;LSA = 0;i++0 = LedBuff[2];break;
case 3SC = 0;LSB = 1;LSA = 1;i++0 = LedBuff[3];break;
case 4SC = 1;LSB = 0;LSA = 0;i++0 = LedBuff[4];break;
case 5SC = 1;LSB = 0;LSA = 1;i++0 = LedBuff[5];break;
case 6SC = 1;LSB = 1;LSA = 0;i++0 = LedBuff[6];break;
case 7SC = 1;LSB = 1;LSA = 1;i = 00 = LedBuff[7];break;
default :break;
}
}
void interruptTimer0()interrupt 3
{
TH1 = T1RH;
TL1 = T1RL;
LedScan();
}
************Infrared.c************
#include <reg52.h>
typedef unsigned char u8;
typedef unsigned int u16;
sbit IR_INPUT = P3^2;
bit irflag = 0; //红外接收标志
unsigned char ircode[4]; //红外接收代码缓冲区
void InitInfrared()
{
IR_INPUT = 1;
TMOD &= 0xf0;
TMOD |= 0x01;
TR0 = 0; //禁止T1定时和中断
ET0 = 0;
IT0 = 1; //设置INT1负边沿触发
EX0 = 1; //使能
}
/*获取高电平持续时间*/
u16 GetHighTime()
{
TH0 = 0; //清零计数值
TL0 = 0;
TR0 = 1;
while(IR_INPUT) //引脚为1时循环等待检测,变零时结束本次循环
{
if(TH0 >= 0x40) //18ms时强制退出避免信号异常
{
break;
}
}
TR0 = 0;
return (TH0 * 256 + TL0);
}
u16 GetLowTime()
{
TH0 = 0;
TL0 = 0;
TR0 = 1;
while(!IR_INPUT)
{
if(TH0 >= 0x40)
{
break;
}
}
TR0 = 0;
return(TH0 * 256 + TL0);
}
/*INT1中断服务函数,执行红外接收及其解码*/
void EXINT1_ISR()interrupt 0
{
u8 i,j;
u8 byt;
u16 time;
//接受并判断引导码的9ms低电平
time = GetLowTime();
if((time < 7833) || (time > 8775))
{
IE0 = 0;
return;
}
//接受并判断引导码的4.5ms高电平
time = GetHighTime();
if((time < 3686) || (time > 4608))
{
IE0 = 0;
return;
}
//循环并判定后续4字节
for(i = 0;i < 4;i++)
{
for(j = 0;j < 8;j++)
{
//接受判定bit的560us的低电平
time = GetLowTime();
if((time < 313)||(time > 718))
{
IE0 = 0;
return;
}
//接受每bit高电平时间,并判定该bit的值
time = GetHighTime();
if((time > 313) && (time < 718))
{
byt >>= 1;
}
else if((time > 1345) && (time < 1751))
{
byt >>= 1;
byt |= 0x80;
}
else
{
IE0 = 0;
return;
}
}
ircode = byt;
}
irflag = 1;
IE0 = 0;
}
|