打印

基于MSP430红外遥控的编码与解码实现

[复制链接]
15316|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Plantt|  楼主 | 2018-12-8 11:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
基于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]复制代码


评论
dirtwillfly 2018-12-9 22:45 回复TA
感谢分享 

相关帖子

沙发
heimaojingzhang| | 2018-12-14 11:29 | 只看该作者
看着算法好麻烦啊

使用特权

评论回复
板凳
wowu| | 2018-12-14 12:06 | 只看该作者
为什么红外需要编码呢

使用特权

评论回复
地板
shang21ic| | 2021-5-27 10:13 | 只看该作者
红外编解码可以用YirTX05哦。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

637

主题

901

帖子

4

粉丝