红外线是波长在 750nm~1mm 之间的电磁波,是人眼看不到的光线。红外数据传输一般采用红外波段内的近红外线,波长在0.75μm~25μm 之间。限定所用红外波长在 850nm~900nm。
IrDA1.0 协议基于异步收发器UART,最高通信速率在115.2kbps,简称SIR(Serial Infrared,串行红外协议); IrDA1.1 协议提高通信速率到4Mbps,简称FIR(Fast Infrared,快速红外协议),同时在低速时保留1.0协议规定;之后,IrDA 又推出了最高通信速率在16Mbps 的协议,简称VFIR(Very FastInfrared,特速红外协议)。
红外传输距离在几cm 到几十m,发射角度通常在 0~15°。使用时只能以半双工方式进行红外通信。
器件的发射部分含有驱动器,接收部分含有放大器,并且内部集成有关断控制逻辑。关断控制逻辑在发送时关断接收,以避免引入干扰;不使用红外传输时,该控制逻辑通过 SD 引脚接受指令,关断器件电源供应,以降耗节能。使用器件时需要在 LED 引脚接入适当的限流电阻。大多数红外收发器件带有屏蔽层。该层不要直接接地,可以通过串联一磁珠再接地,以引入干扰影响接收灵敏度。
S3C2440A UART 模块支持红外的收发功能,可以通过ULCONn(UART 线性控制寄存器)的红外模式位来设置。
9.1 主程序
void xmain(void)
{
char IrDAMode;
ChangeClockDivider(3,1);
ChangeMPllValue(127,2,1); //405MHZ
Isr_Init();
Uart_Select(0);
Uart_Init(0, 115200);
Uart_Printf("\nGEC2440 IrDA Test start\n");
Uart_Printf("press 'R' test RX program\n");
Uart_Printf("press 'T' test TX program\n");
Uart_Printf("press other keys test end\n");
IrDAMode = Uart_Getch();
switch(IrDAMode)
{
case 'T'://红外模块发送测试程序
Test_IrDA_Tx();
break;
case 'R'://红外模块接收测试程序
Test_IrDA_Rx();
break;
default:
Uart_Printf("\n GEC2440 IrDA Test end \n");
}
while(1);
}
9.2 红外模块发送测试程序
void Test_IrDA_Tx(void)
{
int i;
IrDA_cnt=0;
IrDA_end=0;
IrDAdataFl=(volatile U8 *)IrDABUFFER;
IrDAdataPt=(volatile U8 *)IrDABUFFER;
IrDA_Port_Init();
for(i=0;i<IrDA_BUFLEN;i++) *IrDAdataFl++=i; // Initialize IrDA Tx data
pISR_UART2=(U32)IrDA_TxInt;
Uart_Printf("\nSelect the baud rate\n"); // Select IrDA baud rate
Uart_Printf("1)9600 2)19200 3)38400 4)57600 5)115200\n");
i=Uart_Getch ();
switch(i)
{
case '1':
IrDA_BAUD=9600;
break;
case '2':
IrDA_BAUD=19200;
break;
case '3':
IrDA_BAUD=38400;
break;
case '4':
IrDA_BAUD=57600;
break;
case '5':
IrDA_BAUD=115200;
break;
default:
break;
}
rUBRDIV2=( (int)(PCLK/16./IrDA_BAUD) -1 );
Uart_Printf("rUBRDIV2=%d\n", rUBRDIV2);
Uart_Printf("[UART IrDA Tx Test]\n");
Uart_Printf("Start Rx first and press any key and...\n");
Uart_TxEmpty(1);
//transmit FIFO=16B;receive FIFO=1B;Tx FIFO reset;Rx FIFO reset;FIFO Enable
rUFCON2=(1<<6)|(0<<4)|(1<<2)|(1<<1)|(1);
//Tx and Rx FIFO Trigger Level:4byte,Tx and Rx FIFO Reset,FIFO on
rUCON2=(0<<10)|(1<<9)|(1<<8)|(0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<2)|(0); // From H/W
//Infrared Tx/Rx mode;No parity;One stop bit;8bit
rULCON2=(1<<6)|(0<<3)|(0<<2)|(3); // IrDA,No parity,One stop bit, 8bit
Uart_Getch();
rUCON2 |= (1<<2); // Tx enable
Uart_Printf("Now... Tx with IrDA\n");
//开UART2 中断及子中断
rINTMSK=~(BIT_UART2);
rINTSUBMSK=~(BIT_SUB_RXD2|BIT_SUB_TXD2|BIT_SUB_ERR2);
while(!IrDA_end);//发送结束
//关UART2 子中断
rINTSUBMSK|=(BIT_SUB_RXD2|BIT_SUB_TXD2|BIT_SUB_ERR2);
//transmit FIFO=48B;receive FIFO=32B;Tx FIFO reset;Rx FIFO reset;FIFO disable
rUFCON2=(3<<6)|(2<<4)|(1<<2)|(1<<1)|(0);
Uart_Printf("\nEnd Tx, transfer data count=%d\n",IrDA_cnt);
}
9.3 红外模块接收测试程序
void Test_IrDA_Rx(void)
{
unsigned int i;
IrDA_cnt=0;
IrDA_end=0;
IrDA_err=0;
IrDAdataPt =(volatile U8 *)IrDABUFFER; //IrDABUFFER=0x31000000 ;IrDA_BUFLEN=0x100
for(i=0;i<IrDA_BUFLEN;i++) *IrDAdataPt++=0; // Initialize IrDA Tx data = 0
IrDAdataPt =(volatile U8 *)IrDABUFFER;
pISR_UART2=(unsigned)IrDA_RxOrErr;//UART2->IrDA
Uart_Printf("\nSelect the baud rate\n"); // Select IrDA baud rate
Uart_Printf("1)9600 2)19200 3)38400 4)57600 5)115200\n");
i=Uart_Getch();
switch(i)
{
case '1':
IrDA_BAUD=9600;
break;
case '2':
IrDA_BAUD=19200;
break;
case '3':
IrDA_BAUD=38400;
break;
case '4':
IrDA_BAUD=57600;
break;
case '5':
IrDA_BAUD=115200;
break;
default:
break;
}
rUBRDIV2=( (int)(PCLK/16./IrDA_BAUD) -1 );
Uart_Printf("rUBRDIV2=%d\n", rUBRDIV2);
Uart_Printf("[UART IrDA Rx Test]\n");
Uart_Printf("Press any key to start Rx and then Start Tx....\n");
//transmit FIFO=16B;receive FIFO=1B;Tx FIFO reset;Rx FIFO reset;FIFO Enable
rUFCON2=(1<<6)|(0<<4)|(1<<2)|(1<<1)|(1);
//PCLK;Level;Level;Disable Rx time out interrupt;Generate receive error status interrupt.
//Normal operation;Normal transmit;Tx Disable;Rx Disable
rUCON2=(0<<10)|(1<<9)|(1<<8)|(0<<7)|(1<<6)|(0<<5)|(0<<4)|(0<<2)|(0); // From H/W
//Infrared Tx/Rx mode;No parity;One stop bit;8bit
rULCON2=(1<<6)|(0<<3)|(0<<2)|(3);
Uart_Getch();//press any KEY
Uart_Printf("Now... Rx with IrDA\n");
rUCON2 |= 1; // Rx enable, Interrupt request or polling mode
//开UART2 中断及子中断
EnableIrq(BIT_UART2);
EnableSubIrq(BIT_SUB_RXD2);
EnableSubIrq(BIT_SUB_ERR2);
//接收结束或者串口输入回车
while(!IrDA_end) if(Uart_GetKey()=='\r') break;
//关UART2 子中断
rINTSUBMSK|=(BIT_SUB_RXD2|BIT_SUB_TXD2|BIT_SUB_ERR2);
//transmit FIFO=48B;receive FIFO=32B;Tx FIFO reset;Rx FIFO reset;FIFO disable
rUFCON2=(3<<6)|(2<<4)|(1<<2)|(1<<1)|(0);
Uart_Printf("\nEnd Rx, receive data count=%d\n",IrDA_cnt);
IrDAdataPt =(volatile U8 *)IrDABUFFER;
for(i=0;i<IrDA_BUFLEN;i++)
{
if(i-(*IrDAdataPt))
{
Uart_Printf("i=%d,",i);
IrDA_err++;
}
else
Uart_Printf("%d,",*IrDAdataPt++);
}
if(IrDA_err)
Uart_Printf("IrDA test fail!! Error count=%d\n",IrDA_err);
else
Uart_Printf("\nIrDA test is good!!\n");
}