写在梦想边上 https://passport2.21ic.com/?583043 [收藏] [复制] [RSS]

日志

利用状态机实现红外解码

已有 922 次阅读2010-12-23 02:37 |系统分类:单片机

第一篇文章到现在差不多一年了,但是很少更新,自己都觉得不好意思了。正好手头上面有一个关于类似红外解码的问题,感觉以前写的比较烂(也就是我博客里面的第一篇文章中的程序),这次重新写一次。这次只用到一个定时器和一个I/O口,并且使用的是状态机的方法。





需要注意的是①定时器分辨率需要在0.05ms的时候解码的响应速度才会块,当然你也可以将分辨率调得更高,但是需要注意的是分辨率不能够高得定时器中断里面的程序都运行不了,时间太短了,这样会导致定时不准。②在对高电平时间和低电平时间进行计数的时候为了防止干扰的影响,当计数大于一个数的时候复位到READY状态。


程序大概如下:


/**********************************************/
/*IR*/
#define  T_IR         P3_3
#define  HIGH         1
#define  LOW          0


#define  NEC          1
#define  KAIRUI       2


#define  IRMODE       KAIRUI     


#if   (IRMODE == NEC)        


//需要在定时器为0.05ms时响应比较快
#define  Max_IR_time       640    
//32ms*20
#define  HEAD_HIGH_TIME    180    
//9ms*20   //跟输入波形是反的
#define  HEAD_LOW_TIME     90    
//4.5ms*20
#define  ONE_HIGH_TIME     10    
//0.56ms
#define  ONE_LOW_TIME      34    
//1.69ms
#define  ZERO_HIGH_TIME    10    
//0.565ms
#define  ZERO_LOW_TIME     10    
//0.56ms


#define  HEAD_HIGH_TIME_REVISE  40
#define  HEAD_LOW_TIME_REVISE  30
#define  ONE_HIGH_TIME_REVISE  4
#define  ONE_LOW_TIME_REVISE   10
#define  ZERO_HIGH_TIME_REVISE  4
#define  ZERO_LOW_TIME_REVISE  4


#elif  (IRMODE == KAIRUI)
#define  Max_IR_time     640   
//32ms*20
#define  HEAD_HIGH_TIME    320   //16ms*20 
//跟输入波形是反的
#define  HEAD_LOW_TIME    320   //16ms*20
#define  ONE_HIGH_TIME    40   //2ms*20
#define  ONE_LOW_TIME    40   //2ms*20
#define  ZERO_HIGH_TIME    60   //3ms*20
#define  ZERO_LOW_TIME    20   //1ms*20


//20%
#define  HEAD_HIGH_TIME_REVISE  100//64
#define  HEAD_LOW_TIME_REVISE  100//64
#define  ONE_HIGH_TIME_REVISE  10//8
#define  ONE_LOW_TIME_REVISE   10//8
#define  ZERO_HIGH_TIME_REVISE  15//12
#define  ZERO_LOW_TIME_REVISE  5//4
#endif



#define  ONE     1
#define  ZERO    2
#define  None    0


#define  HEAD_HIGH   4
#define  HEAD_LOW   5
#define  CODE_HIGH   6
#define  CODE_LOW   7


/**********************************************/


void init_IR(void)
{
 uint8 i;
 
 tick.Low = 0;
 tick.High = 0;
 
 IR.Low_time = 0;
 IR.High_time = 0;
 
 for(i=0;i<SIZE_OF_IRCode;i++)
 {
  IR.coding_reg = 0; 
 }
 
 IR.Sta = READY;
 IR.type = None;
 
 IR.Count = 0;
 
}


uint8 decode_IR(void)
{
 uint8 the_bit = 0;
 uint8 i;
 uint8 ptr;
 //对头码进行解码
 if((IR.Sta == READY || IR.Sta == HEAD_HIGH) && T_IR == HIGH)//head high
 {
  if(tick.High < Max_IR_time)
  {
   tick.High ++;
   IR.Sta = HEAD_HIGH;LED_OFF();
  }
  else
  {
   init_IR();
   return 0;
  }
 }
 if(IR.Sta == HEAD_HIGH && T_IR == LOW)//head low
 {
  IR.High_time = tick.High;
  tick.High = 0;
  //if(IR.High_time > (HEAD_HIGH_TIME - 40) && IR.High_time < (HEAD_HIGH_TIME + 40))
  //{
   IR.Sta = HEAD_LOW; 
  //}  
 }
 if(IR.Sta == HEAD_LOW && T_IR == LOW)//head low
 {
  if(tick.Low < Max_IR_time)
  {
   tick.Low ++; 
  }
  else
  {
   init_IR();
   return 0;
  }        
 }
 if(IR.Sta == HEAD_LOW && T_IR == HIGH)//HEAD OVER
 {
  IR.Low_time = tick.Low;
  tick.Low = 0;
  if(IR.High_time > (HEAD_HIGH_TIME - 40) && IR.High_time < (HEAD_HIGH_TIME + 40) && IR.Low_time > (HEAD_LOW_TIME - 30) && IR.Low_time < (HEAD_LOW_TIME + 30))
  {
   IR.Sta = RECEIVE;
   IR.type = 'D';  
  }
  else
  {
   init_IR();
   return 0;
  }
 }
 //对数据进行解码
 if((IR.Sta == RECEIVE || IR.Sta == CODE_HIGH) && T_IR == HIGH)
 {
  if(tick.High < Max_IR_time)
  {
   tick.High ++;
   IR.Sta = CODE_HIGH;
  }
  else
  {
   init_IR();
   return 0;
  }   
 }
 if(IR.Sta == CODE_HIGH && T_IR == LOW)//CODE low
 {
  IR.High_time = tick.High;
  tick.High = 0;
  IR.Sta = CODE_LOW;
 }
 if(IR.Sta == CODE_LOW && T_IR == LOW)//CODE low
 {
  if(tick.Low < Max_IR_time)
  {
   tick.Low ++; 
  }
  else
  {
   init_IR();
   return 0;
  }        
 }
 if(IR.Sta == CODE_LOW && T_IR == HIGH)//ONE CODE OVER
 {
  IR.Low_time = tick.Low;
  tick.Low = 0;
  //ZERO
  if(IR.High_time > (ZERO_HIGH_TIME - 4) && IR.High_time < (ZERO_HIGH_TIME + 4) && IR.Low_time > (ZERO_LOW_TIME - 4) && IR.Low_time < (ZERO_LOW_TIME + 4))
  {
   IR.Sta = RECEIVE;
   the_bit = ZERO;  
  }
  //ONE
  else if(IR.High_time > (ONE_HIGH_TIME - 4) && IR.High_time < (ONE_HIGH_TIME + 4) && IR.Low_time > (ONE_LOW_TIME - 10) && IR.Low_time < (ONE_LOW_TIME + 10))
  {
   IR.Sta = RECEIVE;
   the_bit = ONE; 
  }
  else
  {
   init_IR();
   return 0;
  }
 }


 if(the_bit)
 {
  IR.Count ++;
  if(IR.Count <= (SIZE_OF_IRCode*8))
  {
   ptr = (IR.Count+7)/8-1;
   
   IR.coding_reg[ptr] <<= 1;
   if(the_bit == ZERO)
   {
    the_bit = None;
    IR.coding_reg[ptr] &= Bin(11111110);
   }
   else if(the_bit == ONE)
   {
    the_bit = None;
    IR.coding_reg[ptr] |= Bin(00000001);
   }
   if(IR.Count == (SIZE_OF_IRCode*8))
   {
    for(i=0;i<SIZE_OF_IRCode;i++)
    {
     IR.coding = IR.coding_reg;
    }
    init_IR();
    IR.send = 1;
   }
  }
 }
}


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)