⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 红外.c

📁 一种空调的红外线解码源代码
💻 C
字号:
#include <at89x51.H>
#define IR_SYSCODE 0x00
#define SEGMENT P0
#define BIT_LED P2

void  delay_100us(void);
void key_process(void);
void ir_init(void) ;
void display(void) ;
void breakdata(void);
void delay1s(void);

unsigned char ir_data;
bit ir_flag;
unsigned char ir_repeat;

unsigned char data display_bit,display_buffer[8];
unsigned char data time0_h,time0_l;
unsigned int idata time0_times;

unsigned int showdata;
unsigned char data TEMP;
int *point;
unsigned int shdata;
unsigned int keyin;
unsigned int kbempty;
unsigned char dataIR[6];//dataIR 0:syscode0
unsigned char width;    //       1:syscode1


/**********************主程序********************************************************/
void main( void)  
{
	int q;
		
	ir_init();
	
	for(q=0;q<5;q++)
	{
		P0_7=1;
		delay1s();
		P0_7=0;
		delay1s();
	}
	   
	while(1)
	{
		unsigned int l,m;
		for(m=0;m<6;m++)
		{
			for(l=0;l<2000;l++)
		    {
				showdata=dataIR[m];
				display();
			}
		}
				  
		   //display();
		   
		   
		   /*1showdata=dataIR[1];
           display();
           delay1s();
		   showdata=dataIR[2];
		   display();
           delay1s();
		   showdata=dataIR[3];
		   display();
           delay1s();
		   showdata=dataIR[4];
		   display();
           delay1s();
		   showdata=dataIR[5];
		   display();
		   delay1s();*/
	}
		    
}

void ir_init(void)
{
       IE = 0x00;
       EA = 1;
       IT1 = 1;
       EX1 = 1;    /* Enable External Interrupt1 INT1 */ 
       ir_flag = 0;   /* Initialize ir_flag, Receive success mark. */
       ir_repeat = 0;   /* Initialize ir_repeat, Repear mark. */
       ir_data = 0;
	   display_bit=1;
	   dataIR[6]=0X00;
	   
}
/***************中断程序*****************************************/
void ir_svr(void) interrupt 2
{
	   
	unsigned char i=0;      //       2:data
	   
	EX1 = 0;                //       3:data negation
	width = 0x00;           //       4:oxoo end-mark     

	while(!P3_3) /* 计算引导电平的宽度 , 常规状态下INT1为高电平,由高电平跳变为低电平时(即下降沿)产生中断 */
	{
		delay_100us();//引导信号:9ms低电平
		width++;
 	}
	if (width < 80)   /* 8ms=80*100us 如果不到8ms视为干扰信号 */
	{
		EX1 = 1;   /*  if low-level short than 9ms,then reset receiver 允许外部中断*/
		return;
	}
      // 计算4.5ms低电平宽度  
	width = 0x00;
	while(P3_3)  /* Wait for boot signal 4.5ms high-level */
	{
		delay_100us();
		width++;  /* note width */
	}
	
/* 判断是否是重复信号 2.5ms */
	if (width < 30)  /* 3ms=30*100us 如果不到3ms即视为2.5ms重复信号 */
	{
         ir_repeat++;
         if(ir_repeat>2)
		 {
             ir_flag = 1;
             ir_repeat = 0;
		  }
         EX1 = 1;
         return;
        }
         ir_repeat = 0;
		 
 /* Receive new_press */
// 4.5ms新键码引导电平
	if (width < 40)   /* 4ms=40*100us 如果不到4ms视为错误信号,放弃接收 */
	{
		EX1 = 1;
		return;
	}
	
// 至此,引导码已校验,以下接收地址码和数据码,一共32位 
	while(i++ <48)   /* receive 32bits */
	{
		while(!P3_3);  /* Wait for 0.5625ms low-level passed  */
		width = 0x00;
		while(P3_3)  /* Wait for data signal high-level "1" 1680us; "0" 560us */ 
		{
			delay_100us();
			width++;  /* note high-level width */
		}
		ir_data <<= 1;
		if (width > 0x08) /* identify "1" or "0" */
             ir_data |= 0x01; 
		if (i==8)    /* note IR_receive data */
             dataIR[0] = ir_data;
		if (i==16)
             dataIR[1] = ir_data;
		if (i==24)
             dataIR[2] = ir_data;
		if (i==32)
             dataIR[3] = ir_data; 
		if (i==40)
		     dataIR[4]=ir_data;
		if (i==48)
		     dataIR[5]=ir_data; 	  
	}
/*      if (dataIR[2] != ~dataIR[3])  // 纠错较验
           {
            EX1 = 1;
            return;
            }*/
// 判断地址码是否正确
//     if(dataIR[0] != IR_SYSCODE)
//        return;
        ir_data = dataIR[2];
        ir_flag = 1;      /* receive successful flag */
        EX1 = 1;
	   for(i=0;i<4;i++)
	    {	P0_7=1;
		   delay1s();
		   P0_7=0;
		   delay1s();
		   delay1s();
		}
		
        }
/***********************************************************************************/
void polling_ir(void)
{
 if(!ir_flag)  // if no key press, direct return.
    return;
 else
     ir_flag = 0;
// 功能处理
 if(INT0)
      P1 = ir_data;   // display key_code to P1 with BCD
 else
     key_process();   // execute special function
      //_nop_();
}
// 延时 100us
// crystal frequence: 12M  Tosc = 1us
// DJNZ 指令 双字节 两周期 耗时 2*Tosc = 2*1us = 2us
// delay time = 2us * 48 = 96us
void delay_100us(void)
{
 unsigned char i=48;
   while(--i);
}
/****************display    *********************/
/***********************************************/
unsigned char get_code (unsigned char i)
     {
	  unsigned char p;
	  switch(i)
	    { 
		case  0:	p=0x3F;	break;	/*0*/
        case  1:    p=0x06;	break;	/*1*/
        case  2:    p=0x5B;	break;	/*2*/ 
        case  3:    p=0x4F;	break;	/*3*/
        case  4:    p=0x66;	break;	/*4*/
        case  5:    p=0x6D;	break;	/*5*/
        case  6:    p=0x7D;	break;	/*6*/
        case  7:    p=0x07;	break;	/*7*/
        case  8:    p=0x7F;	break;	/*8*/
        case  9:    p=0x67;	break;	/*9*/
        case 10:    p=0x77;	break;	/*A*/
        case 11:    p=0x7C;	break;	/*B*/
        case 12:    p=0x39;	break;	/*C*/
        case 13:    p=0x5E;	break;	/*D*/
        case 14:    p=0x79;	break;	/*E*/
        case 15:    p=0x71;	break;	/*F*/
        case 16:    p=0x00;	break;	/*灭灯*/
        default:            break;
	    }	
	  return ((~p) & 0x7F);
	  }
	    
/**************************************************/	 
void display(void)
     {
	  int f;
	  //showdata=dataIR[2];
	  breakdata();
	  for(f=0;f<6;f++) 
	      {unsigned char i;
		    switch(display_bit)
              {
			  case 1:i=0;break;
			  case 2:i=1;break;
			  case 4:i=2;break;
			  case 8:i=3;break;
			  case 16:i=4;break;
			 // case 32:i=5;break;
			 // case 64:i=6;break;
			 // case 128:i=7;break;
			  default:break;
			  }
	     BIT_LED=0;
		 SEGMENT=get_code(display_buffer[i]);
		 TEMP=SEGMENT;
		 BIT_LED=display_bit;
		 if(display_bit<0X32)
		     {display_bit=display_bit*2;}
	     else display_bit=0x01;
		 }
	  } 		 
			 
/******************数据拆分**********************/
void  breakdata(void)
     { int j;
	   for(j=0;j<6;j++)
	    {
	     display_buffer[j]=showdata%16;
	     showdata=showdata/16;
		 //*(point+1);
	     }
	  
     }
/*******************************延时13us*********************************/
void delay1s(void)
     {int i,j,k;
	  for(i=0;i<100;i++)
	      {for(j=0;j<30;j++)
		        {for(k=0;k<1;k++);}
		   }		  
	  }
/*	通常来说不器可以,但是最好配置一个计数器,主要用来做带宽处理,方便与由于硬件造成速率偏差的校正 [smilez] 2005-10-23 14:19:27 

·	不好:所有的ir处理在中断处理!这不好 [xiaoliu5116] 2005-10-23 15:11:41 
有更好的方法:每次中断,读Time值,得到一位数据的值:lead code 或repeat code 或数
!这样,系统反映速度快!ltisn的方法有个问题:一次ir解收 如果你的系统有led,当有ir时,你的led闪的很厉害!*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -