1736|0

3836

帖子

19

TA的资源

纯净的硅(中级)

楼主
 

MSP430红外遥控的编码与解码 [复制链接]

此编码为常见的红外遥控编码,可以完成红外遥控或红外数据的传输


主要算法:
编码: 用3278Hz频率(P2.0第二功能输出ACLK)驱动红外二极管发送数据(应为38KHz 红外接收头要求,我用的是近距离模拟的,考虑到定时器资源宝贵,暂用32K代替,经验证近距离可以完成传输,使用是可以改为由TA的P1.2输出,稍微改下程序即可:初始化TA,让P1.2口输出38K的pwm波,宏定义中的BIT_0/1改为P1.2口的第二功能开关即可)
发送时先由TB的CCR0的中断控制时间完成9ms的红外发射和4.5ms的停止 然后用CCR0和CCR4的中断完成数据的发送
解码:CCR5定时没450ms中断一次对数据进行检测发现低电平进入数据帧判断 若引导码和起始码正确则进入数据接收逻辑,完成数据段接收


红外编解码.c
/***************************红外编解码.c***************************************/
//  * NAME          : 红外编解码.c
//  * FUNCTION      : 红外的编码与解码
//  * PROGRAMMED    : 刘中原
//  * DATE(ORG)     : 2010.10.12
//  * PROJECT       : 430红外遥控,数据传输
//  * OS            : 所使用的操作系统
//  * HISTORY       :
//  * ID --- DATE -----------NOTE--------------------------
//  * 00 94.04.14 初期完成
//  * 01 94.05.14 第二版 XX机能修改(追加)
//
//编解码波形(NEC)
//________________         __  __   __
//                |        | | | |  |
//                |        | | | |  |
//                |        | | | |  |
//                |        | | | |  |
//                |        | | | |  |.....................................
//                |        | | | |  |
//                |        | | | |  |
//                |________| |_| |__|   "0"高:0.56ms+低:0.565ms=1.125ms
//|<-    9ms    ->|<-4.5ms>|"0"| "1"|   "1"高:0.56ms+低:1.69ms =2.25ms
//|<-  引导码   ->|<-起始码|<-8位地址->|<-8位地址->|8位数据->|<-数据反码->|
//
//可以完成编码 解码  注释掉#define DECODE移去解码部分 #define ENCODE移去编码
//send**是发送完成标志,完成后置1  未完成时连发数据无效
//
//占用资源:TB CCR0中断 CCR4 CCR5中断  CCR0赋值为1125 时钟1MHz
//红外输出端P2.0 32768Hz
//P2.1为红外输入端口
//
/******************************************************************************/


//
#define DECODE      //解码
#define ENCODE      //编码


#include "msp430x16x.h"
#include "红外编解码.h"


/**********************************宏定义**************************************/
#ifdef ENCODE                        /*=======编码=======*/


#define BIT_0     P2SEL&=~BIT0                //红外编码后的低电平
#define BIT_1     P2SEL|=BIT0                 //红外编码后的高电平
#define SENDDAT   TBCCTL0|=CCIE           //启动数据发送 发送已存入addr0和dat0的数据
//发送数据位高位部分 开始发数据位
#define SENDBIT   TBCCR4=565-1;TBCCTL4|=CCIE
#define SEND_END  TBCCTL0&=~CCIE;TBCCTL4&=~CCIE         //发送结束 关中断


#endif                                        /*=======编码=======*/


#ifdef DECODE                        /*=======解码=======*/


#define DATIN   ((P2IN&BIT1)>>1)              //数据输入


#endif                                        /*=======解码=======*/
/******************************************************************************/


#ifdef DECODE                        /*=======解码=======*/
//解码后保存数据
char addr1;
char dat1;
char read** = 0;                //成功读红外数据标志
#endif                                        /*=======解码=======*/


#ifdef  ENCODE                        /*=======编码=======*/
//要编码的数据  发送缓存
char addr0;
char dat0;
char send** = 1;                //发送完成标志
#endif                                        /*=======编码=======*/


//初始化TB
void int_TB()
{
        TBCTL = TBSSEL_2 + TBCLR + MC_1;      //TB时钟源:SMCLK 增模式
        TBCCR0 = 1125 - 1;
        
        TBCCTL5 |= CCIE;
        TBCCR5 = 450;
}


//有关端口初始化
void int_io()
{
  
#ifdef  ENCODE                        /*=======编码=======*/
  //ACLK输出作为编码的载波
        P2OUT &=~ BIT0;
        P2DIR |= BIT0;
#endif                                        /*=======编码=======*/
  
#ifdef DECODE                        /*=======解码=======*/
  //解码输入端口P2.1
        /*P2IES |= BIT1;
        P2IFG &=~ BIT1;
        P2IE |=BIT1;*/
#endif                                        /*=======解码=======*/
  
}


//初始化红外相关资源
void int_hw()
{
        int_TB();
        int_io();
}


#ifdef ENCODE                        /*=======编码=======*/
//编码发送数据,eos标志最后数据一般为1,发送多字节数据时,最后一字节是1
void sendDat(char addr,char dat)
{
        if(send**)                //上次发送完成
        {
                //数据存入发送缓存
                addr0 = addr;
                dat0  = dat;
                //开始发送
                SENDDAT;
        }
}
#endif                                        /*=======编码=======*/


#ifdef DECODE
//红外数据解码函数
void datDecode(unsigned int tAddr, unsigned int tDat)
{
        if(((tAddr>>8)&0xff)==(tAddr&0xff))                //地址高位低位相等 地址位数据正确
        {
                addr1 = tAddr&0xff;
                if(((tDat>>8)&0xff)==((~tDat)&0xff))                //数据高位低位反 数据位数据正确
                {
                        dat1 = ~(tDat&0xff);
                        read** = 1;
                }
                else
                {
                        read** = 2;
                }
        }
        else
        {
                read** = 2;
        }
        
}
#endif




//中断


#ifdef ENCODE                        /*=======编码=======*/
//TB0中断 编码
#pragma vector=TIMERB0_VECTOR
__interrupt void Timer_B (void)
{
    static char i = 0;    //计数 起始
    static char state = 0;    //状态 起始:0  数据:1
    static char cnt = 0;      //发送计数
        
    if(state==0)
    {
        if(i==0)
        {
            BIT_1;
                        
                        //完成标志置0 开始发送
                        send** = 0;
        }
        else if(i==8)
        {
            BIT_0;
        }
        else if(i==11)
        {
            SENDBIT;
            state = 1;
                        
                        i = 255;
        }
   
    }
    else if(state==1)
    {
        BIT_0;
   
        if(cnt<8)               //地址高位
        {
            if(addr0&(1<<(7-cnt)))       //从高位到低位 是1延时+2:2.25ms
            {
                if(i==1)
                {
                    SENDBIT;
                    i = 255;
                                cnt++;    //发送加1
                }
            }
            else
            {
                SENDBIT;
                i = 255;
                        cnt++;    //发送加1
            }
        }
        else if(cnt<16)                //地址低位
        {
            if(addr0&(1<<(15-cnt)))       //从高位到低位 是1延时+2:2.25ms
            {
                if(i==1)
                {
                        SENDBIT;
                    i = 255;
                                cnt++;    //发送加1
                }
            }
            else
            {
                SENDBIT;
                i = 255;
                        cnt++;    //发送加1
            }
        }
                else if(cnt<24)                //数据
                {
                        if(dat0&(1<<(23-cnt)))       //从高位到低位 是1延时+2:2.25ms
                {
                if(i==1)
                {
                        SENDBIT;
                    i = 255;
                                cnt++;    //发送加1
                }
                        }
                        else                          //是0延时+1:1.125ms
                        {
                SENDBIT;
                i = 255;
                        cnt++;    //发送加1
                        }
                }
                else if(cnt<32)                //数据反码  
                {
                        if((~dat0)&(1<<(31-cnt)))       //从高位到低位 反码是1延时+2:2.25ms
                        {
                if(i==1)
                {
                        SENDBIT;
                    i = 255;
                                cnt++;    //发送加1
                }
                        }
                        else                          //是0延时+1:1.125ms
                        {
                SENDBIT;
                i = 255;
                        cnt++;    //发送加1
                        }
                }
                /*else if(cnt==32)        //最后多发一位0,否则无法识别最后一位
                {
                        
                SENDBIT;
                i = 255;
                        cnt++;    //发送加1
                }*/
                else
                {
                        //完成标志置1
                        send** = 1;
                        
                        //变量归零
                        state = 0;
                        cnt = 0;
                        i = 255;
                        SEND_END;                //停止发送
                        
                        BIT_0;
                }
   
    }
   
    i++;      //计数加1
        
        TBCCTL4 &=~ CCIFG;                //中断标志清除
}


#endif                                        /*=======编码=======*/


//TB1中断
#pragma vector=TIMERB1_VECTOR
__interrupt void Timer_B1(void)
{
  static int i = 0;         //计数变量 接收用
  static char state = 0;   //代表接收状态的变量
  static char cnt = 0;                //读取位数计数


  
  switch( TBIV )
{
        case  0x08:                          // TBCCR4 编码发送数据位部分
#ifdef ENCODE                        /*=======编码=======*/
                BIT_1;
                TBCCTL4 &=~ CCIE;
#endif                                        /*=======编码=======*/
                break;
    case  0x0a:                          // TBCCR5 解码用
#ifdef DECODE                        /*=======解码=======*/
                TBCCR5 = (TBR+440>1124)?(TBR+440-1124):(TBR+440);
                if(TBCCR5>1124) TBCCR5 = 1124;                                                //防止TBCCR5出界


                i++;


                if(DATIN==0&&read**>0)                //上次读取完成(可能有错误 read**=2 错误数据) 又有数据到来
                {
                        read** = 0;
                        i = 0;
                }
                if(state==0&&read** == 0)                        //起始码
                {
                        if(i<15&&DATIN)                //引导码有高电平 错误数据帧
                        {
                                read** = 2;
                        }
                        else if(i>26&&DATIN==0X01)                //引导码正确 准备读数据
                        {
                                state = 1;                //1状态 读数据
                                
                                i = 0;
                        }
                }
                else if(state==1)                //数据
                {
                        static unsigned int tAddr = 0;                //地址位临时变量
                        static unsigned int tDat = 0;                //数据位临时变量
                        
                        static char dat** = 0;
                        if(cnt<16)                        // 地址 位
                        {
                                if(DATIN==0x00&&dat**==0)
                                {
                                        dat** = 1;                        //有数据
                                       
                                        i = 0;
                                }
                                if((i==2||i==3)&&dat**&&DATIN==0X00)
                                {
                                        tAddr |= (0X00)<<(15-cnt);
                                        i = 0;
                                        dat** = 1;
                                        cnt++;
                                        return;
                                }
                                else if((i==3)&&DATIN==0X01&&dat**)
                                {
                                        tAddr |= (0X01)<<(15-cnt);
                                        i = 0;
                                        dat** = 0;
                                        cnt++;
                                }
                                else if(i>3)
                                {
                                        read** = 2;
                                        cnt = 0;
                                        dat** = 0;
                                        tAddr = 0;
                                        tDat = 0;
                                       
                                        state = 0;
                                }
                        }
                        else if(cnt<32)                        //数据位接收
                        {
                                if(DATIN==0x00&&dat**==0)
                                {
                                        dat** = 1;                        //有数据
                                       
                                        i = 0;
                                }
                                if((i==2||i==3)&&dat**&&DATIN==0X00)
                                {
                                        tDat |= (0X00)<<(31-cnt);
                                        i = 0;
                                        dat** = 1;
                                        cnt++;
                                        return;
                                }
                                else if((i==3)&&DATIN==0X01&&dat**)
                                {
                                        tDat |= (0X01)<<(31-cnt);
                                        i = 0;
                                        dat** = 0;
                                        cnt++;
                                }
                                else if(i>3)
                                {
                                        read** = 2;
                                        cnt = 0;
                                        dat** = 0;
                                        tAddr = 0;
                                        tDat = 0;
                                       
                                        state = 0;
                                }
                                
                        }
                        else
                        {
                                datDecode(tAddr, tDat);
                                //解码结束
                                i = 0;
                                
                                cnt = 0;
                                state = 0;
                                dat** = 0;
                                tAddr = 0;
                                tDat = 0;
                        }
                }
               
#endif                                        /*=======解码=======*/
                break;
    case  0x0e:                       //overflow 溢出,未用
                break;
  }
}


/*
#ifdef DECODE                        =======解码=======*/
//PORT2中断 此中断仅解码接收数据用
/*#pragma vector=PORT2_VECTOR
__interrupt void PORT2_ISR(void)
{
        switch(DATIFG&BIT1)
        {
        case 2:
                //开始接收数据
                DATREAD;      
                break;
        }
  
        DATIFG = 0;                        //清除标志位
}


#endif                                        =======解码=======*/


[color=rgb(51, 102, 153) !important]复制代码




红外编解码.h
#ifndef __HW_H
#define __HW_H


extern char send**;                //发送完成标志


void int_hw();
void sendDat(char addr,char dat);


#endif /* __HW */


[color=rgb(51, 102, 153) !important]

 
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表