/*********************************************************************/
#include <reg52.h>
#include <intrins.h>
sbitIRIN = P3 ^ 2; //红外接收器数据线
sbit BEEP = P3 ^ 7; //蜂鸣器驱动线
sbit RELAY = P1 ^ 3; //继电器驱动线
unsigned char IRCOM[] =
{
0x00, 0x00, 0x00, 0x00, 0x10, 0x10
};
unsigned char code table[] =
{
0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8,//0,1,2,3,4,5,6,7
0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e, 0xbf //8,9,A,B,C,D,E,F,-
};
char code reserve[3]_at_ 0x3b; //保留0x3b开始的3个字节
/**********************************************************
ms延时子函数
**********************************************************/
void delayms(unsigned int ms)
{
unsigned char k;
while (ms--)
{
  for (k = 0; k < 114; k++)
  ;
}
}
/**********************************************************
us延时子函数
**********************************************************/
void delay(unsigned char x) //x*0.14MS
{
unsigned char i;
while (x--)
{
  for (i = 0; i < 14; i++)
  ;
}
}
/**********************************************************
蜂鸣器驱动子函数
**********************************************************/
void beep()
{
unsigned char i;
for (i = 0; i < 100; i++)
{
  BEEP = !BEEP; //BEEP取反
  delay(6);
}
BEEP = 1; //关闭蜂鸣器
}
/**********************************************************
显示函数
**********************************************************/
void play()
{
P0 = (table[IRCOM[4]]); //个位
P2 = 0xfe;
delayms(1);
P0 = (table[IRCOM[5]]); //十位
P2 = 0xfd;
delayms(1);
P2 = 0xff; //关闭显示
delayms(1);
}
/**********************************************************
主函数
**********************************************************/
void main(void)
{
P0 = 0xff; //I/O口初始化
P2 = 0xff;
IRIN = 1;
BEEP = 1;
RELAY = 1;
IE = 0x81; //允许总中断中断,使能 INT0 外部中断
TCON = 0x01; //触发方式为脉冲负边沿触发
play();
while (1)
{
  if (IRCOM[2] == 0x1d)
  //UP键
  RELAY = 0;
  //继电器吸合
  if (IRCOM[2] == 0x12)
  //DOWN键
  RELAY = 1;
  //继电器关闭
  play(); //显示
}
}
/**********************************************************
INT0 中断服务子函数
**********************************************************/
void IR_IN()interrupt 0
{
unsigned char j, k, Num = 0;
EX0 = 0; //关闭INT0中断
delay(15); //延时
if (IRIN == 1)
//再确认IR信号是否出现
{
  EX0 = 1; //开INT0中断
  return ; //退出
}
while (!IRIN)
//等IR变为高电平,跳过9ms的前导低电平信号。
{
  delay(1);
}
while (IRIN)
//等IR变为低电平,跳过4.5ms的前导高电平信号。
{
  delay(1);
}
for (j = 0; j < 4; j++)
//收集四组数据
{
  for (k = 0; k < 8; k++)
  //每组数据有8位
  {
  while (IRIN)
  //等 IR 变为低电平
  {
  delay(1);
  }
  while (!IRIN)
  //等 IR 变为高电平
  {
  delay(1);
  }
  while (IRIN)
  //计算IR高电平时长
  {
  delay(1);
  Num++;
  if (Num >= 15)
  {
    EX0 = 1; //0.14ms计数过长自动离开。
    return ;
  }
  } //高电平计数完毕
  IRCOM[j] = IRCOM[j] >> 1; //数据最高位补“0”
  if (Num >= 8)
  IRCOM[j] = IRCOM[j] | 0x80;
  //数据最高位补“1”
  Num = 0;
  } //end for k
} //end for j
if (IRCOM[0] != 0x00)
//比较用户码
{
  EX0 = 1; //开INT0中断
  return ; //退出
}
if (IRCOM[2] != ~IRCOM[3])
//接收数据是否正确
{
  EX0 = 1; //开INT0中断
  return ; //退出
}
IRCOM[4] = IRCOM[2] &0x0F; //取键码的低四位
IRCOM[5] = IRCOM[2] >> 4; //右移4次,高四位变为低四位
play(); //显示键码
beep(); //蜂鸣器响一声
EX0 = 1; //重新开INT0中断
}
/**********************************************************
;================================
;6121码 遥控器(晶控电子)
;******红外遥控器键值表******
00  01  02  03
04  05  06  07
08  09  0A  0B
0C  0D  0E  0F
10  11  12  13
14  15  16  17
18  19  1A  1B
;================================
IRCOM[0] --- 存放用户码  00H
IRCOM[1] --- 存放用户反码ffH
IRCOM[2] --- 存放数据码
IRCOM[3] --- 存放数据反码
*********************************************************/