|
这是为什么啊?????以下是红外解码程序:
//lcd1602显示键值
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
//定义数组
uchar HL_Time[33]={0};//存储高低电平的时间
uchar BYTE[4]={0};//存放码(用户码,用户反码,数据码,数据反码)
uchar table[16]={"IR_CODE:0x "};//lcd2602初始化显示的
//标志位
bit decode_ok = 0;//解码标志位。decode_ok=1解码成功,decode-ok=0解码失败
bit trans_ok = 0;//时间转换标志位。trans_ok=1转换成功,trans_ok =0转换失败
bit head_ok = 0;//引导码接受标志位,head_ok=1引导码接受成功,head_ok=0 引导码接受失败
bit head_start= 0; //引导码开始接收标志位
//定义变量
uchar Timer0_Count=0; //时间计数器,Timer0_Count每加1,时间经过250us
uchar Init0_Count=0;//外部中断0计数器,Init0_Count每加1,就经历了一次下降沿
//位定义led接口
sbit lcd_E=P2^7;
sbit lcd_RS=P2^6;
sbit lcd_RW=P2^5;
void delayms(uint z)
{
uint x,y;
for(x=1;x<z;x++)
for(y=1;y<110;y++);
}
void write_commend(uchar commend)
{
lcd_RS=0;
lcd_RW=0;
P0=commend;
delayms(2);
lcd_E=1;
delayms(5);
lcd_E=0;
delayms(2);
}
void write_data(uchar date)
{
lcd_RS=1;
lcd_RW=0;
P0=date;
delayms(2);
lcd_E=1;
delayms(5);
lcd_E=0;
delayms(2);
}
//1602显示字符串函数(y=1时显示在第一行,y=2显示在第二行。x表示从第x个开始显示)
void write_str(uint y,uint x,uchar * str)
{
uint i;
if(y==1)
{
write_commend(0x80+x-1);
for(i=0;i<16;i++)
write_data(*(str+i));
}
else
{
write_commend(0x80+0x40+x-1);
for(i=0;i<16;i++)
write_data(*(str+i));
}
}
//输入字符函数(y=1时显示在第一行,y=2显示在第二行。x表示从第x个开始显示)
void write_char(uint y,uint x,uchar value)
{
if(y==1)
{
write_commend(0x80+x-1);
write_data(value);
}
else
{
write_commend(0x80+0x40+x);
write_data(value);
}
}
//lcd显示16进制数函数
void write_16(uint x,uint y,uchar dat)
{
uchar j;
j=dat>>4; //把要显示内容的高4位移到低4位上
if(j<10) //0-F在ASCII码中并不连续,所以要分开处理
{
j+='0'; //0-9的数据以0为基点进行偏移即可
}
else
{
j=j-10+'A'; //A-F的数据以A为基点进行偏移即可
}
write_char(x,y,j); //在第x行的第y列显示高4位的十六进制数字
j=dat&0x0F; //把要显示内容的高4位屏蔽掉,保留低4位
if(j<10) //0-F在ASCII码中并不连续,所以要分开处理
{
j+='0'; //0-9的数据以0为基点进行偏移即可
}
else
{
j=j-10+'A'; //A-F的数据以A为基点进行偏移即可
}
write_char(x,y+1,j); //在第x行的第y+1列显示低4位的十六进制数字
}
void init_lcd()
{
lcd_E=0;
write_commend(0x38);
write_commend(0x0e);
write_commend(0x06);
write_commend(0x01);
write_commend(0x80);
write_str(1,1,&table);
}
//初始化外部中断0
void Init_EX0()
{
IT0 = 1;//外部中断0下降沿触发方式
EX0 = 1;//开外部中断0
EA = 1;//开总中断
}
//初始化定时器0
void Init_T0()
{
TMOD=0X01;//设置定时器0位工作方式1
TH0=(65535-250*(11059200/12000000))/256; //设定计数初值,计数250us
TL0=(65535-250*(11059200/12000000))%256; //设定计数初值,计数250us
ET0=1; //允许定时器0中断
TR0=1;//开定时器0
}
//将HL_Time[]数组中的时间转化为逻辑1或逻辑0;
void Transform_Time()
{
uint i,j;
uint num=1;//等于1是为了抛弃HL_Time[0]这个元素,因为这个元素存放的是引导码的时间
uchar IR_CODE=0; //存储接收到的码
for(j=0;j++;j<4) //两个for循环,循环一次接收好一字节的数据,循环4次,接收一字节时循环8次
{
for(i=0;i<8;i++)
{
if(HL_Time[num]>7) //接收1
IR_CODE |= 0X80;
else //接收0
IR_CODE = IR_CODE;
IR_CODE >>= 1;
num++;
}
BYTE[j]=IR_CODE;
IR_CODE=0x00;//得到一个数据后清零以便接收下一个数据
}
if(BYTE[2]=~BYTE[3])//判断数据是否正确
trans_ok=1;
}
//主函数
void main()
{
init_lcd();
Init_EX0();
Init_T0();
while(1)
{
if(decode_ok)//解码成功
{
decode_ok=0;//清零以备下次接收
Transform_Time();//开始执行时间转换
}
if(trans_ok)//时间转换成功
{
trans_ok=0;//清零以备下次接收
write_16(1,11,HL_Time[2]);//显示数据码
}
}
}
//红外中断函数
void IR_Decode() interrupt 0
{
if(head_start==0)//按下按键后就开始进入第一次中断
{
head_start=1;//标志着引导码接受开始
Timer0_Count=0;//时间计数器清零
}
else if(head_start==1)//下面开始解码
{
if((Timer0_Count>=52)&&(Timer0_Count<=56))//引导码时间为13.5ms即13500us,是250us的54倍,故把Time_Count规定在51到57这个区间,提高容错率
{
Init0_Count=0;//中断计数器清零
}
HL_Time[Init0_Count]=Timer0_Count;//给时间数组赋值
//因为每过250us Timer0_Count就会增加1,而只有当外部中断0产生中断时Timer0_Count的值才会被
//记录到HL_Time[]数组里,所以如果数组中的元素在3~5表示这次外部中断接收的是0,
//在8~10表示此次外部中断接收的是1
//也可以以6位分水岭。Timer0_Count大于6是1,小于6是0
//逻辑0持续时间1.12ms,1120/250=4.48
//逻辑1持续时间2.25ms,2250/250=9
Timer0_Count=0;//为下存时间值做准备
Init0_Count++;
if(Init0_Count==33)
{
Init0_Count=0;//中断计数清零
decode_ok=1;//存时间值的任务成功,即解码成功
head_start=0;//清零以备下次解码任务的完成
}
}
}
//定时器0中断函数
void Timer0()interrupt 1
{
TH0=(65535-250*(11059200/12000000))/256; //设定计数初值,计数250us
TL0=(65535-250*(11059200/12000000))%256; //设定计数初值,计数250us
Timer0_Count++;
} |
|