ts19891230 发表于 2012-8-3 09:20:34

msp430f149红外解码程序

void Init_Sys(void)
{
   unsigned int i;
   BCSCTL1&=~XT2OFF;               //打开XT2振荡器
   do
   {
      IFG1 &= ~OFIFG;                  // 清除振荡器失效标志
      for (i = 0xFF; i > 0; i--);      // 延时,等待XT2起振
   }
   while ((IFG1 & OFIFG) != 0);      // 判断XT2是否起振
   BCSCTL2 =SELM_2+SELS; //选择MCLK、SMCLK为XT2
    //以下对各种模块、中断、外围设备等进行初始化
}
void Init_irt(void)
{
   P1DIR &=~BIT1; //设置P1.1为输入
   P1SEL |= BIT1; //设置P1.1为CCI0A输入
   TACTL=TASSEL_2+MC_2+ID_3;//aclk=32768Hz、连续计数模式、8分频
   CCTL0=CM_2+SCS+CCIS_0+CAP+CCIE;
   //下降沿捕获、同步捕获、选择输入为CCI0A、捕获模式、开捕获中断
}
void IR_data_pros (void)
{
uchar i,j,count=1,value;   // count=1 、作用是清除引导码
for(i=0;i<4;i++)
{
    for(j=0;j<8;j++)
    {
      value>>=1;
      if(ir_data>1700)//判断捕获时间是否大于1.7MS 我想请问一下各位大神,这个1700是怎么依据得到?      value|=0x80;             //若 >1.7MS,则为1、若 <1.7MS,则为0
      count++;
    }
    ir_code=value;          //存放用户码和数据码
}
dataok=1;                  //数据处理标志置位
}
void deal_irt(void)
{
if(irok)                  //数据接收是否完毕?
    {
      irok=0;                   //是、清标志位
      IR_data_pros();         //红外数据处理函
    }
if(dataok)                  //数据处理是否完毕?
    {
      dataok=0;               //是、清标志位
    }
}
#pragma vector=TIMERA0_VECTOR
__interrupt void timera (void)
{
    static uchar index;
    if(diff_cap>7000) index=1;       //检测引导码各位大神 我想问一下7000怎么来的    new_cap=TACCR0;                  
    diff_cap=new_cap - old_cap;
    ir_data=diff_cap;       //存捕获的差异值,既是数据
    if(index==33)                  //数据接收完毕
    {
   index=0;                        
   irok=1;                         //数据接收标志置位
    }
    old_cap=new_cap;               
}
我的MCLK用的是8M ,TACTL用的是32768,8分频捕获

512826028 发表于 2012-8-11 19:18:38

这个程序是你烤的的别人的吗?你在你的板子上实验通过了没有呢?
那个延时肯定是和单片机的延时时间有关的啊。一般,32的红外遥控码需要4.5ms的延时,还有9ms的延时。这个需要考虑单片机工作在一个什么频率下面。

512826028 发表于 2012-8-11 21:52:54

下面的这个程序是我的一个可用的程序。可用给你参考一下了。
板子是MSP430F413的。直接了一个32768k的晶振。没有接高速晶振。显示用的LCD。这个不重要。

#include<msp430x41x.h>

unsigned long recode;   //接收码
unsigned intrecodehigh,recodelow; //接收码的高低16位
unsigned char hongwaicode;   //定义一个4字节的数组用来存储代
unsigned char CodeTemp;   //编码字节缓存变量
unsigned char i,j,k;    //延时用的循环变量

/***************************************************************
通用数组函数digit[]

***************************************************************/
const char table =
{
0x7D,// '0'    LCD segments a+b+c+d+e+f
0x60,// '1'
0x3E,// '2'
0x7A,// '3'
0x63,// '4'
0x5B,// '5'
0x5F,// '6'
0x70,// '7'
0x7F,// '8'
0x7B,// '9'
0x77,// 'a'
0x4f,// 'b'
0x1d,// 'c'
0x6e,// 'd'
0x1f,// 'e'
0x17   // 'f'
};

void delayms(int ms)
{
    char i;
    while(ms--){
          for(i=0;i<255;i++);
    }
}
/*******************************************************
初始化定时器函数
*******************************************************/
void InitTimer(void)
{
    //TACTL = TASSEL0 + MC0;//ACLK 单调递增模式
    //CCTL0 = CCIE;         
    //TACCR0= 4096;      //定时时间是1s
   
    TACTL |= TASSEL0
            + MC0 + TACLR;
    //使用32768Hz晶振工作
    //初始化定时器 UP 模式,计数到CCR0
    TACCR0 = 9999;
}
/**************************延时0.9ms子程序**********************/

void Delay0_9ms(void)

{
InitTimer();
while(TAR<=29);
TACTL = 0;//停止计数
TAR = 0;
}

/***************************延时1ms子程序**********************/

void Delay1ms(void)

{
InitTimer();
while(TAR<=34);
TACTL = 0;//停止计数
TAR = 0;
}

/***************************延时4.5ms子程序**********************/

void Delay4_5ms(void)

{
InitTimer();
while(TAR<=145);
TACTL = 0;//停止计数
TAR = 0;
}

/*******************************************************
初始化LCD函数
******************************************************/
void InitLCD(void)
{
    LCDCTL = LCDP0+LCDP1 + LCD4MUX + LCDON;
    //液晶开启S0_S23端口,4 mux驱动方式打开LCD
    P5SEL= 0XFC;
    //设置P5口为对应的COM口和R接口。
}

/********************************************************
清屏LCD的函数
********************************************************/
void ClearLCD()
{
    char i;
    for(i=0;i<11;i++)
      LCDMEM=0;
}

/********************************************************
主函数main
******************************************************/

void main(void)
{      

WDTCTL = WDTPW + WDTHOLD;               // Stop WDT
SCFQCTL = 0xff;//使用最高速度有助于显示的速度和灵敏性

//InitTimer();         //初始化定时器A0
InitLCD();         //初始化LCD控制器

ClearLCD();          //清屏

P1DIR = 0X00;// 置为输入
P1IE= 0X40;//P1.6置为中断使能
P1IES = 0XFF;//下降沿触发

__enable_interrupt();

LCDCTL = LCDP0+LCD4MUX+LCDON;             // 选择液晶端口为S0-S15 1/4周期并且打开液晶输出
//LCDACTL |= LCDFREQ_128;
BTCTL= BT_fLCD_DIV32;                   // 选择液晶的晶振速度为32.768K/128
P5SEL= 0xFF;                            // Set Rxx and COM pins for LCD
// _BIS_SR(LPM3_bits + GIE);                                  // 打开总中断

    while(1)
    {
      ClearLCD();          //清屏
    }
}


#pragma vector = PORT1_VECTOR
__interrupt void intp1()
{
    P1IE= 0X00;//P1.6置为中断禁止
    if(P1IFG & 0X40)
    {
      for(k=0;k<10;k++)
      {
          
      Delay0_9ms();
   
      if ((P1IN&0x40)==1)         //如果0.9ms后IRDATA=1,说明不是引导码

            {k=10;break;}
   
    else if(k==9)         //如果持续了10×0.9ms=9ms的低电平,说明是引导码

         {
                       
            while((P1IN&0x40)==0);
                               
            Delay4_5ms();      //跳过持续4.5ms的高电平
            for(i=0;i<4;i++)       //分别读取4个字节
                       
            {
                for(j=1;j<=8;j++)      //每个字节8个bit的判断

                {
                                               
                  while((P1IN&0x40)==0);       //等待上升沿

                  Delay0_9ms();      //从上升沿那一时刻开始延时0.9ms,再判断IRDATA
                  if((P1IN&0x40)==0x40)   //如果IRDATA是"1",则向右移入一位"1"
       
                  {
                                                       
                      Delay1ms();
                                                       
                      CodeTemp=CodeTemp|0x80;
                                       
                      if(j<8) CodeTemp=CodeTemp>>1;
                               
                  }
                                               
                  else if(j<8)
                                                  
                  CodeTemp=CodeTemp>>1;//如果IRDATA是"0",则向右移一位,自动补"0"
                }
                                       
                hongwaicode=CodeTemp;
                                       
                CodeTemp=0;
                               
            }
               
         }
       
       }
//end of for(k=0;k<10;k++)
      recodehigh=hongwaicode<<8|hongwaicode;

      recodelow=hongwaicode<<8|hongwaicode;

      recode=recodehigh;

      recode=recode<<16;

      recode=recode|recodelow;
   
    LCDMEM = table>>4];
    LCDMEM = table&0x0f];
    LCDMEM = table>>4];
    LCDMEM = table&0x0f];
    LCDMEM = table>>4];
    LCDMEM = table&0x0f];
    LCDMEM = table>>4];
    LCDMEM = table&0x0f];
    delayms(2500);
    }
    P1IFG = 0;
    P1IE= 0X40;//P1.6置为中断使能
}

512826028 发表于 2012-8-11 21:58:58

上面的那个程序是解码32位红外遥控码的。
第一个延时0、9ms,延时10次就等于9ms了。
延时计算是这样的:
外部晶振32768.    1/ 32768 = 0x030517ms
这个是定时器使用ACLK时计一个数使用的时间。
计数到29的时间是0.885ms。可以认作是0.9ms。
后面的延时函数,依次类推。

sunliezhi 发表于 2012-8-11 22:39:09

尽量不用延时函数,用状态机。
页: [1]
查看完整版本: msp430f149红外解码程序