#include <reg52.h>
#include <intrins.h>
#define MAIN_Fosc 11059200UL //宏定义主时钟HZ
//解码红外信号的关键(NEC)是测量每个信号的时间
typedef unsigned char INT8U;
typedef unsigned char uchar;
typedef unsigned int INT16U;
typedef unsigned int uint;
uchar IRtime; //储存检测红外信号持续时间
uchar IRcord[4]; //储存解码后4个字节(2用户码,数据码,数据反码)
uchar IRdata[33]; //包含起始码的数据
bit IRpro_ok; //解码后4个字节数据接受完成标志位
bit IRok; //33位数据接受完成标志位
sbit FM=P2^3;
sbit DU = P2^6; //数码管段选
sbit WE = P2^7; //数码管位选
/*====================================
共阴极数码管段选码
====================================*/
uchar code table[]={
//0 1 2 3 4 5 6 7 8
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F,
//9 A B C D E F - . 关显示
0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x40, 0x80, 0x00
};
/*====================================
数码管位选码
====================================*/
//第1位 2位 3位 4位 5位 6位 7位 8位
uchar code T_COM[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};//数码管位码
/*====================================
函数:void Delay_Ms(INT16U ms)
参数:ms,毫秒延时形参
描述:12T 51单片机自适应主时钟毫秒级延时函数
====================================*/
void Delay_Ms(INT16U ms)
{
INT16U i;
do{
i = MAIN_Fosc / 96000;
while(--i); //96T per loop
}while(--ms);
}
/*====================================
函数:void Display(INT16U Value)
参数:Value,显示值 取值0-65535
描述:共阴极数码管显示函数可显示一个字节的数
====================================*/
void Display(uchar Value) //注意由于需要显示的数大于一个字节所有形参需为int型
{
//------------------------------
DU = 0; //关闭段选
P0 = table[Value/16]; //数码管显示百位
DU = 1; //打开段选
DU = 0; //关闭段选
WE = 0; //关闭位选
P0 = T_COM[0]; //第一位数码管
WE = 1; //打开位选
WE = 0; //关闭位选
Delay_Ms(3);
DU = 0; //关闭段选
P0 = table[Value%16]; //数码管显示百位
DU = 1; //打开段选
DU = 0; //关闭段选
WE = 0; //关闭位选
P0 = T_COM[1]; //第一位数码管
WE = 1; //打开位选
WE = 0; //关闭位选
Delay_Ms(3);
}
//利用计时器0来进行计数 ,外部中断0,串口
void init()
{
EA=1;
TMOD |=0x02;//设置定时器零工作模式2,8位自动重装
TL0=0; //定时器配置
TH0=0;
ET0=1;
TR0=1;
IT0=1; //外部中断0配置
EX0=1;
TMOD |=0X20;//设置定时器1工作模式2,用于串口通信
TL1=0xfd;//9600比特率
TH1=0xfd;
SM1=1; //串口工作模式1,10位异步收发
TR1=1; //启动定时器1
}
void time0() interrupt 1
{
IRtime++;//每中断一次需要256个周期,一个机器周期位1.085us,因此时间为277.76us
}
//外部中断0存入33位脉宽
void int0() interrupt 0
{
static uchar i;//静态变量
static bit startflag;//存贮标志位
if(startflag)
{
if ((IRtime<53)&&(IRtime>=32)) //起始码位9~15ms
i=0;
IRdata[i]=IRtime;//存储时间
IRtime=0;
i++;//计数器存入下一位脉宽
if(i==33)
{
IRok=1;
i=0;
startflag=0;
}
}
else//开始计数
{
IRtime= 0;
startflag=1;
}
}
void IRcordpro()
{
uchar i; //计数处理四个字节
uchar j; //计数处理一个字节的8位数据
uchar k; //用于处理33为脉宽
k=1;//忽视起始码
for(i=0;i<4;i++)
for(j=0;j<8;j++)
{
if((IRdata[k])>5) //数据0《1.125ms
IRcord[i]|=0x80;
if(j<7)//防止最低位溢出
IRcord[i]>>=1;
k++;//处理下一次脉宽
}
IRpro_ok=1;
}
void main()
{
uchar i;//计数串口发送字节数
init();
while(1)
{
if(IRok)
{
IRok=0; //清零脉冲检测
IRcordpro();//运行解码函数
if(IRpro_ok)
{
IRpro_ok=0;
for(i=0;i<4;i++)
{
SBUF=IRcord[i];//发送
while(!TI)
Display(IRcord[i]);
TI=0;
}
if(IRcord[2]==0x45)
FM=~FM;
}
}
Display(IRcord[2]);
}
}