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分频捕获 这个程序是你烤的的别人的吗?你在你的板子上实验通过了没有呢?
那个延时肯定是和单片机的延时时间有关的啊。一般,32的红外遥控码需要4.5ms的延时,还有9ms的延时。这个需要考虑单片机工作在一个什么频率下面。 下面的这个程序是我的一个可用的程序。可用给你参考一下了。
板子是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置为中断使能
} 上面的那个程序是解码32位红外遥控码的。
第一个延时0、9ms,延时10次就等于9ms了。
延时计算是这样的:
外部晶振32768. 1/ 32768 = 0x030517ms
这个是定时器使用ACLK时计一个数使用的时间。
计数到29的时间是0.885ms。可以认作是0.9ms。
后面的延时函数,依次类推。 尽量不用延时函数,用状态机。
页:
[1]