红外通信的主要注意几个方面:430单片机的时钟配置(我选择内部DCO,为了准确的定时器捕获脉冲)、红外通信协议的数据格式(用户数据是从高到低还是从低到高?)、430单片机的一些寄存器配置。 程序如下:
#include " msp430g2452.h"
typedef unsigned int uint;
typedef unsigned char uchar;
uint ir_data[33];//存放解码数据(16位用户码+8位数据码+8位数据反码)
uchar ir_code[4];//存放解码数据
uchar irok=0;//数据接收标志位
uint new_cap=0;
uint old_cap=0;
uint diff_cap=0;
uchar data_sign=0;
void clk_init(void);//时钟初始化
void timera_init (void);
void IR_data_pros (void);
void main( void ) {
uint i;
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
for(i = 0; i < 0xFFFF; i++){};
_BIS_SR(OSCOFF);
if(CALBC1_1MHZ==0xff||CALDCO_1MHZ==0xff)
{
while(1); }
clk_init();
timera_init(); //定时器初始化
_EINT(); //开总中断开关
while(1) {
if(irok) //数据接收是否完毕?
{
irok=0; //是、清标志位
IR_data_pros(); //红外数据处理函
//if(ir_code[2]==(~(ir_code[3])))
// P1OUT ^=BIT6;//绿灯
//else P1OUT ^=BIT0;//红灯
P2OUT=ir_code[2]>>4;
}
}
}
/*************************************************************/
void clk_init(void) {
DCOCTL=CALDCO_8MHZ; /* DCOCTL Calibration Data for 8MHz */
BCSCTL1=CALBC1_8MHZ;//使MCLK=DCOCTL=8MHz
BCSCTL2 |=SELM_0+DIVS_0+DIVM_0; //使MCLK=SMCLK=DCO=8M
}
/*************************************************************/
void timera_init (void) {
P2DIR=0xff;
P2OUT=0x00;
P1DIR &=~BIT1; //设置P1.1为输入
//P1DIR |=BIT6+BIT0;
//P1OUT &=~BIT6;
//P1OUT &=~BIT0;
P1SEL |= BIT1; //设置P1.1为CCI0A输入
TACTL=TASSEL_2+MC_2+TACLR+ID_3; //timera_clk=SMclk=1MHz、连续计数模式、1分频
CCTL0=CM_2+SCS+CCIS_0+CAP+CCIE;
//下降沿捕获、同步捕获、选择输入为CCI0A、捕获模式、开捕获中断
}
/*********************红外数据处理函数**************************/
void IR_data_pros (void) {
uchar i,j,count=1,value=0; // count=1 、作用是清除引导码
for(i=0;i<4;i++)
{
value=0;
for(j=0;j<8;j++)
{
value>>=1; //用户码和数据码均是低位在前,高位在后
if(ir_data[count]>1700) //判断捕获时间是否大于1.7MS
value|=0x80; //若 >1.7MS,则为1、若 <1.7MS,则为0
count++;
}
ir_code=value; //存放用户码和数据码
}
}
/********************Timer_A中断服务程序*************************/
#pragma vector=TIMER0_A0_VECTOR
__interrupt void timera (void) {
static uchar index=0;
new_cap=TACCR0;
if(data_sign==0)
{
data_sign=1;
old_cap=new_cap;
return
}
if(new_cap<old_cap)//计数重新开始
diff_cap=65536-old_cap+new_cap;
else diff_cap=new_cap - old_cap;
if(diff_cap>7000){index=0; } //检测引导码
ir_data[index++]=diff_cap; //存捕获的差异值,既是数据
if(index==33) //数据接收完毕
{
index=0;
data_sign=0;
irok=1; //数据接收标志置位
}
old_cap=new_cap;
}
使用定时器A的捕获模式来计算脉冲宽度,来区分1或者0.
|