使用环境:
处理器: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(); } } }
|