|
此编码为常见的红外遥控编码,可以完成红外遥控或红外数据的传输
主要算法:
编码: 用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]
|
|