由于刚开始接触单片机,所以做出来的程序也许不代表什么,程序还有一点点工作没有做,但是你可以在任何一个网站找代码,就是16B的非0即1数据转化为1B的问题,在程序中均有详细的说明,采用的是INT0,INT1,非门双中断,T0,T1双定时,更详细的请看程序,有什么好的想法,可以和我交流,最好的联系方式为Msn,由于我接触单片机只有 短短两个月,这里采用的是At89C52芯片,外电路不要找我,因为我采用的是最简电路.
详细程序如下(Keil C编译成功):
/* title 红外解码方式程序设计*/
/*芯片的固有属性为起始位为低电平触发,也就是说采用反向双触发方式第三次出发就为需要的码*/
/*引导码9msL+4.5msH*/
#define CLK_CPU 11.0592
#include <AT89X52.H>
bit flag; /* 定义中断标志*/
bit status; /*中断来源 INT0=0;INT1=1*/
unsigned int *px; /*存储解码信号*,第一位存储码数*/
struct code_end
{
unsigned int number;
unsigned char *compressdata; /*把数据压缩后存储*/
}code_end;
unsigned int *time_high; /*记录高电平持续时间 第一位为引导脉冲高点平*/
unsigned int *time_low;
unsigned int time_stand; /*脉冲基数,即为低电平时间*/
unsigned int count_intr; /*中断产生的次数,这里去除了引导玛*/
bit overlow_sign; /*溢出标志*/
bit start_recieve=0;
void get_time_stand();
void write_data();
unsigned int int0_count; /*低脉冲触发次数*/
unsigned int int1_count; /*高脉冲触发次数*/
bit rec_time();
/*记录高低电平的时间*/
void service_int0() interrupt 0 using 2 /* 中断0设置标志*/
{
flag=1;
status=0;
int0_count++;
if(int0_count> 1)
start_recieve=1;
else
start_recieve=0;
}
void service_int1() interrupt 1 using 2
{
flag=1;
status=1;
int1_count++;
if(int0_count> 1)
start_recieve=1;
else
start_recieve=0;
}
void timer0_init() /*定时器0初始化*/
{
TMOD = 0x11; /*定时器0 1 均工作在1状态*/
TH0 = 0x00;
TL0 = 0x00;
TR0=0;
}
void timer1_init() /* 定时器1初始化*/
{
TMOD = 0x11;
TH1 = 0x00;
TL1 = 0x00;
TR1=0;
}
bit IR_init() /*红外信号接收初始化*/
{
/*这里用来获取引导码,包括两个电平*/
/*time_high time_low 第一个存储数据就是相应的引导码的数据*/
/*9ms Low 4.5ms High 格力空调的编码,利用TEK示波器可以获取*/
rec_time();
return start_recieve;
}
void write_data() /*信号保存*/
{
unsigned int i;
unsigned int j;
unsigned int count_loop;
unsigned int sgl;
struct code_end code_end;
*px=count_intr; /*必须保证px的起始位置*/
px++; /*第一位开始存储码*/
for(j=1;j <count_intr+1;j++)
{
if(*time_high> 2*time_stand)/*大于2倍就认为是1*/
*px=1;
else
*px=0;
px++;
}
/*数据一共存储了count_intr个,这里采用的是 unsigned int 格式*/
/*需要进一步压缩来获取最简单模式,code_end */
code_end.number=count_intr;
px=px-code_end.number;
sgl=count_intr%8;
count_loop=(count_intr-sgl)/8; /*设置循环次数*/
for(i=0;i <count_loop;i++)
{
for(j=0;j <8;j++)
{/*移位运算,压缩数据*/
code_end.compressdata++;
}
code_end.compressdata++;
for(i=0;i <sgl;i++)
{
/*不为8的整数,移位运算,压缩数据*/
}
}
/*转化为Bit*/
}
void get_time_stand() /*获取时间基数*/
{
unsigned int i;
unsigned int sum;
sum=0;
time_stand=600; /*这里芯片为600us*/
/*设计获取方式:利用中断0的时间来获取*/
for(i=1;i <count_intr+1;i++)
{
if(count_intr!=0)
sum=sum+(*time_low)/count_intr;
time_low++;
}
time_stand=sum;
}
bit rec_time() /*记录高低电平时间*/
{
while(flag)
{
if(status==0)
{
TR0=1; /*开定时器0*/
TR1=0; /*关闭定时器1,计算时间,并存储*/
if(int0_count!=1) /*不记录第一次中断前的时间*/
{
*time_high=(TL1+TH1*256)/11.0592/1000;
TH1=0;
TL1=0;
time_high++;
}
flag=0;
}
else
{
TR1=1; /*开启定时器1*/
TR0=0; /*关闭定时器0,计算时间,并存储*/
*time_low=(TL0+TH0*256)/11.0592/1000;
TH0=0;
TL0=0;
time_low++;
if(TF1) /*溢出在表示接收结束,最后一位默认为高点平*/
{
overlow_sign=1;
time_high++;
*time_high=0xffff;
}
flag=0;
}
}
return overlow_sign; /*溢出标志*/
}
main()
{
int0_count=0;
int1_count=0;
flag=1;/*调试用*/
count_intr=0;
timer0_init();
timer1_init();
IR_init();
while((!overlow_sign)&&(start_recieve))
{
rec_time();
}
count_intr=int0_count-1;/*除引导码外中断的次数*/
get_time_stand();
write_data();
}