/*******************************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_)也无法解决这个现象,求高手 帮我看看。谢谢了
|