免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1236 | 回复: 0
打印 上一主题 下一主题

ARM普通IO口接收NEC遥控 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-01-06 17:32 |只看该作者 |倒序浏览
使用环境:
    处理器:S3C2440A    IR receiver: HS0038   接收口: GPB9(非中断IO口)
程序设计思路:
    因为是普通IO口接收遥控,不能使用中断来检测IR波形。这里使用查询的方式来进行检测。
    由于遥控波形的不稳定性,一般认为合理误差在20%或30%以内。
    NEC波形的最小水平是560us,所以我们设定一个100us的定时器对IO口做检测。另设置一个计数器对高低电平计数。
注意事项:
   定时器输出时钟频率=PCLK/(prescaler+1)/divider
   其中prescaler值由TCFG0决定,divider值由TCFG1决定,而prescaler只能取0~255之间的整数,divider只能取2、4、8和16。
   如果程序定义多个定时器,要先设定满足多个定时器时钟频率的prescaler,再设定divider.
 
 
以下是部分程序:
 
#define HEAD_LOW_MIN  (63)               //   9000*0.7/100 = 63
#define HEAD_LOW_MAX  (117)             //9000*1.3/100 = 117
#define HEAD_HIGH_MIN  (31)              //4500*0.7/100=31
#define HEAD_HIGH_MAX  (59)        //4500*1.3/100 = 59
#define CODE_LOW_MIN  (4)                //560*0.7/100=3.92
#define CODE_LOW_MAX  (8)       //560*1.3/100 =7.28
#define CODE0_HIGH_MIN  CODE_LOW_MIN  //
#define CODE0_HIGH_MAX  CODE_LOW_MAX
#define CODE1_HIGH_MIN  (12)     //1690*0.7/100 = 11.83
#define CODE1_HIGH_MAX  (22)     //1690*1.3/100 = 21.97
#define REP_LOW_MIN   HEAD_LOW_MIN
#define REP_LOW_MAX   HEAD_LOW_MAX
#define REP_HIGH_MIN   (15)     //2250*0.7/100 = 15.75
#define REP_HIGH_MAX  (30)     //2250*1.3/100 = 29.25
#define FLAME_INTERVAL_MIN   (864)  //108000*0.8/100=864
#define FLAME_INTERVAL_MAX   (1296)  //108000*1.2/100=1296
#define HIGH_LEVEL   (1)
#define LOW_LEVEL    (0)
#define IR_IDLE     0
#define IR_HEAD    1
#define IR_CODES    2
#define IR_REPEAT_9   3
#define IR_REPEAT_2_25  4
#define IR_REPEAT_STOP  5

static U8   last_level;
static U8   ir_state;
static U8  bits_received;  //count how many bits received.
static U8  code_received;      //whether receive a data or not.
static U8  repeat_received; //whether receive a repeat code or not.
static U32   ir_counter;   //count how many  cycle a level last for.
static U32  ir_data;    //record the received IR bits.
static U32  ir_interval_counter;  //record the flame interval. normal 108ms.
static U8  customer_data;
static U8  command_data;
 
int Test_IrDecoder()
{
  Uart_Printf("\n==irda decoder=\n");
  Uart_Printf("press ESC to exit\n");
  rGPBCON&= ~(0x10<<18);    //GPB9:IRDA
  Ir_DecodeError();
                            //TIMER3 is used for delay function.
  rTCFG0 &= ~(0xff<<8);
  rTCFG0 |= 3<<8;           //prescaler = 3
  rTCFG1 &= ~(0xf<<16);
  rTCFG1 |= 3<<16;          //mux = 1/16  utput clock freq. = 50*1000000/16/4;
                            //781250Hz.   cycle=1/781250= 1.28us
  rTCNTB4 =  78;            // 1.28us*75 =100 us. 
  rTCON &= ~(0x07<<20);
  rTCON |= 0x700000;
  rTCON &= ~0x200000;        //clear manual update bit.
  pISR_TIMER4=(U32)IsrTime4;   //set timer4 entry point, that is, install timer.
  rSRCPND = BIT_TIMER4;       //clear the interrupt apply bit.
  rINTPND =  BIT_TIMER4;
  rINTMSK &= ~BIT_TIMER4;    //enable  timer4 
 
  while(1)
  {  
       Delay(10);
       ....
       if ( Uart_GetKey() == ESC_KEY ) break; 
  }
  return(0);
}
 
//NEC
//     9ms         4.5ms  2.25ms
// __            _____  __ _1.12ms
//    |        |       ||  |||
//    |        |       ||  |||
//    |________|       ||  |||
//          head  code       1  0
   
static void __irq IsrTime4(void)
{
 U8   current_level;
 U32 m,m_invert;
 current_level= HIGH_LEVEL;
 
 rSRCPND |= BIT_TIMER4;
 rINTPND |=  BIT_TIMER4;       //Clear
 
 if  ((rGPBDAT&0x200) != 0x200)
 {
  current_level = LOW_LEVEL;
 }
 switch (ir_state)
 {
  case IR_IDLE:
   if (LOW_LEVEL == current_level)
   {
    ir_counter = 1;
    ir_state = IR_HEAD;
   }
   break;
  case IR_HEAD:                 //Ready to receive IR head.
   if (LOW_LEVEL == current_level)
   {
    if (LOW_LEVEL == last_level )
    {
     ir_counter++;
     if (ir_counter > HEAD_LOW_MAX)
     {
      Ir_DecodeError();
     }
    }
    else if (HIGH_LEVEL == last_level)
    {
     if (ir_counter >= HEAD_HIGH_MIN)
     {
      ir_counter = 1;
      ir_state = IR_CODES;            //Head received, ready to receive IR data.  
     }
     else
     {
      Ir_DecodeError();
     }
    }
   }
   else //current_level = High
   { 
    if (HIGH_LEVEL == last_level)
    {
     ir_counter++;
     if (ir_counter > HEAD_HIGH_MAX)
     {
      Ir_DecodeError();
     }
    }
    else
    {
     if (ir_counter >= HEAD_LOW_MIN)
     {
      ir_counter = 1;
     }
     else
     {
      Ir_DecodeError();
     }
    }
   }
   break;
  case IR_CODES:                    //Ready to receive 32-bit IR codes.
   if (LOW_LEVEL == current_level)
   {
    if (LOW_LEVEL == last_level )
    {
     ir_counter++;
     if (ir_counter > CODE_LOW_MAX)
     {
      Ir_DecodeError();
     }
    }
    else if (HIGH_LEVEL == last_level)
    {
     if ((ir_counter >= CODE0_HIGH_MIN) && (ir_counter <=CODE0_HIGH_MAX))
     {
       ir_data = (ir_data >>1);
       ir_data |= 0x00;   // add onr "0" to ir data
       ir_counter = 1;
       bits_received++;
     }
     else if ((ir_counter >= CODE1_HIGH_MIN) && (ir_counter <=CODE1_HIGH_MAX))
     {
       ir_data = (ir_data >>1);
       ir_data |= 0x80000000;   // add onr "1" to ir data
        ir_counter = 1;
       bits_received++;
     }
     else
     {
      Ir_DecodeError();
     }
     
     if ((16 == bits_received)||(32 == bits_received))
     {
      m = ((ir_data>>16) & 0x000000FF);
      m_invert = ((ir_data>>24) &0x000000FF);
      if ((m^m_invert)!=0x000000FF)
      {
       Ir_DecodeError();
      }
      if (32 == bits_received)
      {
       code_received = TRUE;               //First Key received.
       ir_state = IR_REPEAT_9;             //Ready to check whether repeat key
       ir_counter = 1;                     //received or not.
      }
     }
    }
   }
   else //current_level = High
   {   
    if (HIGH_LEVEL == last_level)
    {
     ir_counter++;
     if (ir_counter > CODE1_HIGH_MAX)
     {
      Ir_DecodeError();
     }
    }
    else
    {
     if (ir_counter >= CODE_LOW_MIN)
     {
      ir_counter = 1;
     }
     else
     {
      Ir_DecodeError();
     }
    }
   }
   break;
   
  case IR_REPEAT_9:
   if (ir_interval_counter < FLAME_INTERVAL_MAX)
   {
    if (LOW_LEVEL == current_level)
    {
     if (HIGH_LEVEL == last_level)
     {
      if (ir_interval_counter >= FLAME_INTERVAL_MIN)
      {
       ir_interval_counter = 0;
       ir_counter = 1;
      }
      else
      {
       Ir_DecodeError();
      }
     }
     else
     {
      ir_counter++;
      if (ir_counter > REP_LOW_MAX)
      {
       Ir_DecodeError();
      }
     }
    }
    else //current HIGH level
    {
     if (HIGH_LEVEL == last_level)
     {
      if (ir_interval_counter == FLAME_INTERVAL_MAX)
      {
       Ir_DecodeError();
      }
     }
     else
     {
      if (ir_counter >= HEAD_LOW_MIN)
      {
       ir_state = IR_REPEAT_2_25;
       ir_counter = 1;
      }
      else
      {
       Ir_DecodeError();
      }
     }
    }
   }
   else
   {
    Ir_DecodeError();
   }
   break;
  case IR_REPEAT_2_25:
   if (LOW_LEVEL == current_level)
   {
    if (ir_counter >= REP_HIGH_MIN)
    {
     ir_counter = 1;
     ir_state = IR_REPEAT_STOP;
    }
    else
    {
     Ir_DecodeError();
    }
   }
   else //current HIGH level
   {
    ir_counter++;
    if (ir_counter >= REP_HIGH_MAX)
    {
     Ir_DecodeError();
    }
   }
   break;
   
  case IR_REPEAT_STOP:
   if (LOW_LEVEL == current_level)
   {
    ir_counter++;
    if (ir_counter > CODE_LOW_MAX)
    {
     Ir_DecodeError();
    }
   }
   else //current HIGH level
   {
    ir_counter++;
    if (ir_counter >= REP_HIGH_MAX)
    {
     Ir_DecodeError();
    }
   }
   break;
 }

 if (ir_state != IR_IDLE)
 {
  last_level = current_level;
  ir_interval_counter++;
  if (ir_interval_counter > FLAME_INTERVAL_MAX)
  {
   Ir_DecodeError();
  }
 }
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP