一、实验目的
-
- 掌握红外的编码与调制及解码。
- 掌握红外通信编程的实现。
二、实验内容
- 学习使用定时器生成38KHz频率。
- 学习红外发射与接收程序编程。
三、实验原理
- 实验相关电路图
- 红外协议简介
NEC协议特征:
1、8位地址和8位命令长度
2、每次传输两遍地址(用户码)和命令(按键值)
3、通过脉冲串之间的时间间隔来实现信号的调制(PPM)
4、38Khz载波
5、每位的周期为1.12ms(低电平)或者2.25ms(高电平)
通信信号波形
数据包格式波形
重复包格式波形
位0首先为0.56ms的高电平,然后是0.565ms的低电平;位1首先是0.56ms的高电平,然后是1.69ms的低电平。
四、实验器材
IAR软件开发平台
CC2530开发板
五、实验步骤
- 写38KHz频率输出程序。
- 编写NEC格式的各个模块。
- 编写按键发射程序
- 编写红外数据接收程序。
- 红外数据接收解释程序。
- 编译程序并下载程序到cc2530。
- 使用跳线帽短接P2与P4。
- 按按键发送数据,另一块开发板接收数据,观察是否能通信成功。
- 实验结果(数据和图表)
#include <ioCC2530.h>
#include "lcd12864.h"
#define IR_TX P1_3
#define IR_RX P1_0
#define USERCODE 0xff
unsigned char RxBuf[4],TxBuf[4],rx_over,key_value,rx_flag;
unsigned int N;
void delay_ms(unsigned int n)
{
unsigned int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<980;j++);
}
}
void IR_init(void)
{
P1SEL &= 0xf6;
P1DIR |= 0x08;
P1DIR &= 0xfe;
P1INP |= 0x01;
IR_TX = 0;
P1IEN |= 0x01;
IEN2 |= 0x10;
PICTL |= 0x02; //P1下降沿中断
P1IFG=0;
P1IF=0;
}
//缓冲区9ms
void IR_TX38KHz(unsigned int n)
{
unsigned char i;
while(n--)
{
IR_TX=1;
i=12;
while(i--)
{
asm("nop");
}
IR_TX=0;
i=22;
while(i--)
{
asm("nop");
}
}
}
//缓冲区4.5MS
void IR_TXLOW(unsigned int n)
{
unsigned char i;
while(n--)
{
IR_TX=0;
i=12;
while(i--)
{
asm("nop");
}
IR_TX=0;
i=22;
while(i--)
{
asm("nop");
}
}
}
void IR_sendNEC(unsigned char *dat)
{
unsigned char i,j;
IR_TX38KHz(342); //9ms
IR_TXLOW(180); //4.5ms
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
if(dat[i]&0x01)
{
IR_TX38KHz(22); //560us
IR_TXLOW(64); //1690us
}
else
{
IR_TX38KHz(22); //560us
IR_TXLOW(22); //560us
}
dat[i] >>= 1;
}
}
IR_TX38KHz(22); //560us
}
void time1_init(void)
{
T1IE=0; //关闭T1中断
}
void key_init(void)
{
P2SEL &= 0xf9;
P2DIR &= 0xf9;
P2IEN |= 0x06;
IEN2 |= 0x02;
PICTL |= 0x08; //P2下降沿中断
P2IFG=0;
P2IF=0;
key_value=0;
}
const unsigned char
charBuf[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f',};
void main()
{
unsigned char dispBuf1[17]={'T','X',':','U','=','0','x',' ',' ',' ','D','=','0','x',' ',' ','\0'};
unsigned char dispBuf2[17]={'R','X',':','U','=','0','x',' ',' ',' ','D','=','0','x',' ',' ','\0'};
unsigned char dispBuf3[17]={' ',' ',' ','U','=','0','x',' ',' ',' ','D','=','0','x',' ',' ','\0'};
const unsigned char IRData[2]={0x90,0x60};//输出数据
CLKCONCMD &= ~0x7f;
while(CLKCONSTA & 0x40);
io_init();
initial_lcd();
clear_screen();
IR_init();
key_init();
time1_init();
EA=1;
while(1)
{
if(key_value)
{
TxBuf[0] = 0x21;//按键S1按下
TxBuf[1] = ~TxBuf[0];
TxBuf[2] = IRData[key_value-1];
TxBuf[3] = ~TxBuf[2];
dispBuf1[7]=charBuf[TxBuf[0]>>4];
dispBuf1[8]=charBuf[TxBuf[0]&0x0f];
//
dispBuf1[14]=charBuf[TxBuf[2]>>4];
dispBuf1[15]=charBuf[TxBuf[2]&0x0f];
display_string_8x16(3,1,dispBuf1);
IR_sendNEC(TxBuf);
key_value=0;
}
if(rx_over)
{
dispBuf2[7]=charBuf[RxBuf[0]>>4];
dispBuf2[8]=charBuf[RxBuf[0]&0x0f];
//
dispBuf2[14]=charBuf[RxBuf[2]>>4];
dispBuf2[15]=charBuf[RxBuf[2]&0x0f];
display_string_8x16(5,1,dispBuf2);
dispBuf3[7]=charBuf[RxBuf[1]>>4];
dispBuf3[8]=charBuf[RxBuf[1]&0x0f];
//
dispBuf3[14]=charBuf[RxBuf[3]>>4];
dispBuf3[15]=charBuf[RxBuf[3]&0x0f];
display_string_8x16(7,1,dispBuf3);
rx_over=0;IEN2 |= 0x10;
}
}
}
//中断
#pragma vector = T2_VECTOR
__interrupt void P2_ISR(void)
{
if(P2IFG>0)
{
if(P2IFG&0x02)
{
key_value=1;
}
else if(P2IFG&0x04)
{
key_value=2;
}
else
{
key_value=0;
}
}
P2IFG=0;
P2IF=0;
}
#define T1_start() T1CTL=0x09
#define T1_stop() T1CTL=0x08
#pragma vector = P1INT_VECTOR
__interrupt void P1_ISR(void)
{
unsigned char i,j;
P1IFG = 0x00;
IEN2 &= ~0x10;
if(IR_RX==0)
{
T1CNTL=0;
T1_start();
while(IR_RX==0)
{
N=T1CNTL;
N +=(T1CNTH<<8);
if(N>=9500)goto RX_STOP;
}
T1_stop();
if(N<8500)goto RX_STOP;
T1CNTL=0;
N=0;
T1_start();
while(IR_RX==1)
{
N=T1CNTL;
N +=(T1CNTH<<8);
if(N>=5000)goto RX_STOP;
}
T1_stop();
if(N<4000)goto RX_STOP;
rx_over=0;
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
while(IR_RX==0);
T1CNTL=0;
N=0;
T1_start();
while(N<840)
{
N=T1CNTL;
N +=(T1CNTH<<8);
}
T1_stop();
RxBuf[i]>>=1;
if(IR_RX==1)
{
RxBuf[i] |= 0x80;
}
while(IR_RX==1);
}
}
while(IR_RX==0); //结束标志
rx_over=1;
}
else
{
RX_STOP:
T1_stop();
IEN2 |= 0x10;
}
}