#mspfPWM红外解码C语言.docx

上传人:b****7 文档编号:10864677 上传时间:2023-02-23 格式:DOCX 页数:18 大小:124.05KB
下载 相关 举报
#mspfPWM红外解码C语言.docx_第1页
第1页 / 共18页
#mspfPWM红外解码C语言.docx_第2页
第2页 / 共18页
#mspfPWM红外解码C语言.docx_第3页
第3页 / 共18页
#mspfPWM红外解码C语言.docx_第4页
第4页 / 共18页
#mspfPWM红外解码C语言.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

#mspfPWM红外解码C语言.docx

《#mspfPWM红外解码C语言.docx》由会员分享,可在线阅读,更多相关《#mspfPWM红外解码C语言.docx(18页珍藏版)》请在冰豆网上搜索。

#mspfPWM红外解码C语言.docx

#mspfPWM红外解码C语言

基于msp430f149的PWM红外解码的研究

摘要:

因为红外遥控的实用与经济性,本文研究PWM方式调制的红外解码的实现。

红外线遥控是目前使用最广泛的一种通信和遥控手段。

因为红外线遥控装置具有体积小、功耗低、功能强、成本低等特点,因而,继彩电、录像机之后,在录音机、音响设备、空凋机以及玩具等其它小型电器装置上也纷纷采用红外线遥控。

工业设备中,在高压、辐射、有毒气体、粉尘等环境下,采用红外线遥控不仅完全可靠而且能有效地隔离电气干扰。

1红外遥控系统

通用红外遥控系统由发射和接收两大部分组成,应用编/解码专用集成电路芯片来进行控制操作,如下所示:

<一)发射部分键盘矩阵、编码调制、LED红外发送器

<二)接收部分

研究中应用VS0038一体化红外接收头<实物图如下:

红外接收头VS0038能够正常接收的角度

2遥控发射器及其编码

<1)遥控发射器专用芯片很多

<2)根据编码格式可以分成:

脉冲宽度调制和脉冲相位调制两大类

现在我们研究以运用比较广泛,解码比较容易实现的脉冲宽度调制来加以说明。

当发射器按键按下后,即有遥控码发出,所按的键不同遥控编码也不同。

这种遥控码具有以下特征:

(a)采用脉宽调制的串行码

(b)以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”

(c)以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”

遥控器发出由“0”和“1”组成的32位二进制码,经38kHz的载频进行二次调制以提高发射效率,达到降低电源功耗的目的。

然后再通过红外发射二极管产生红外线向空间发射,,其中前16位为用户识别码,能区别不同的红外遥控设备,防止不同机种遥控码互相干扰。

后16位为8位的操作码和8位的操作反码用于核对数据是否接收正确。

<其中的地址码为用户识别码,它又分为用户码与用户反码)

当遥控器上任意一个按键按下超过36ms时,LC7461芯片的振荡器使芯片激活,将发射一个特定的同步码头,对于接收端而言就是一个9ms的低电平,和一个4.5ms的高电平,这个同步码头可以使程序知道从这个同步码头以后可以开始接收数据。

解码的关键是如何识别“0”和“1”,从位的定义我们可以发现“0”、“1”均以0.56ms的低电平开始,不同的是高电平的宽度不同,“0”为0.56ms,“1”为1.68ms,所以必须根据高电平的宽度区别“0”和“1”。

如果从0.56ms低电平过后,开始延时,0.56ms以后,若读到的电平为低,说明该位为“0”,反之则为“1”,为了可靠起见,延时必须比0.56ms长些,但又不能超过1.12ms,否则如果该位为“0”,读到的已是下一位的高电平,因此取<1.12ms+0.56ms)/2=0.84ms最为可靠,一般取0.84ms左右即可。

根据红外编码的格式,程序应该等待9ms的起始码和4.5ms的结果码完成后才能读码。

接收器及解码

VS0038是塑封一体化红外线接收器,它是一种集红外线接收、放大、整形于一体的集成电路,不需要任何外接元件,就能完成从红外线接收到输出与TTL电平信号兼容的所有工作,没有红外遥控信号时为高电平,收到红外信号时为低电平,而体积和普通的塑封三极管大小一样,它适合于各种红外线遥控和红外线数据传输。

下面是一个msp430f149单片机对红外线遥控器的解码程序,它可以把遥控器的32位码<42位码也可以)的红外遥控器每一个按键的键值读出来,并且通过12864点阵液晶显示编码和键值,在解码成功的同时发出“嘀”的提示音。

并且能把编码保存起来,如果此时按下键盘上第三个键,就把该信号再向外发射出去,不过一次只能存一组数据,如果有兴趣可以把编码存入flash,这样不仅可以保存更多的编码,而且掉电数据也不会丢。

这是我测试时用的遥控器

这是测试的结果,前三行是红外信号的编码,最后一行是8位数据码的十六进制格式,因为我的遥控器采用的是32位二进制码,所以后十位是无效位。

如果是对42位二进制码的遥控器解码时,前26位是系统码,后16位是8位数据码和8位数据反码。

不过此时第四行的十六进制是无效哦。

软件设计思想及流程:

<1)程序使用到的msp430f149单片机的I\O口主要有P4与P6<用于12864液晶驱动)P1.3与P5.2<分别用来实现红外数据的接收和红外数据的发送)。

<2)程序的关键部分是红外解码,而根据红外线发出的红外信号编码的规则可以看出,二进制码“0”和“1”最主要的区别在于脉冲时间的长短,所以根据判断脉冲时间便可以判断是“1”还是“0”。

其程序如下:

<程序已调试通过直接移值就可以用)

#include

#include"config.h"

#defineCPU_F((double>8000000>//CPU主频8MHZ

#definedelay_us(x>__delay_cycles((long>(CPU_F*(double>x/1000000.0>>

#definedelay_ms(x>__delay_cycles((long>(CPU_F*(double>x/1000.0>>

#defineucharunsignedchar

#defineuintunsignedint

/*************红外接收端口定义**************/

#defineHW_IP1DIR&=~BIT3

#defineHW_OP1DIR|=BIT3

#defineHW_LP1OUT&=~BIT3

#defineHW_HP1OUT|=BIT3

#defineHW_Q(P1IN&BIT3>

/**************12864液晶端口定义********/

#defineRS(1<<5>

#defineRW(1<<6>

#defineEC(1<<7>

#definePSB(1<<0>

#defineRST(1<<1>

/**************红外发射端口定义*************/

#defineFS_HP5OUT|=BIT2

#defineFS_LP5OUT&=~BIT2

#defineFS_IP5DIR&=~BIT2

#defineFS_OP5DIR|=BIT2

#defineFS_FP5OUT^=BIT2

#defineFSIEONTACCTL0|=CCIE。

TACCTL1|=CCIE

#defineFSIEOFFTACCTL0&=~CCIE。

TACCTL1&=~CCIE

#defineBUZ_OFFP6OUT|=BIT2

#defineBUZ_ONP6OUT&=~BIT2

ucharflag,ff,mf,num。

intwidth。

//用来设定载波信号的持续时间

uchartable_IR[42]。

//用来存放接收的红外信号编码

uchartable_ir0[]={0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1}。

//"音量-"

uchartable_ir1[]={0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,1,0,1,0,1,1,1}。

//"音量+"

uchartable_lcd[]={48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70}。

//液晶显示数字对应ASIIC

voidLCD_INIT(void>。

//液晶初始化函数声明

voidWRITE_COM(ucharcom>。

//液晶写指令函数声明

voidWRITE_DATA(uchardata>。

//液晶写数据函数声明

charREAD_BF(void>。

//液晶忙检查函数声明

voidinfrared(void>。

//红外接收检测函数声明

voidIR_SEND(uchar*pir>。

//红外发射函数声明

ucharkey(void>。

//矩阵键盘扫描函数声明

voidmain(void>

{

uinti=0。

ucharkeydata。

//存放键值用

WDTCTL=WDTPW+WDTHOLD。

//关闭看门狗

BCSCTL1&=~XT2OFF。

//开启XT2高速晶体振荡器

BCSCTL2|=SELM_2+SELS。

do{

IFG1&=~OFIFG。

for(i=0。

i<100。

i++>_NOP(>。

}

while(IFG1&OFIFG>。

IFG1&=~OFIFG。

Close_LED(>。

//关闭数码管

P5DIR|=RS+RW+EC+PSB+RST。

//初始化液晶相关端口

P6DIR|=BIT2。

//蜂鸣器端口设为输出模式

BUZ_OFF。

//关闭蜂鸣器

HW_L。

HW_I。

//初始化红外接收端口

P1DIR=0x0f。

P1OUT=0x00。

//初始化矩阵键盘端口,红外接收复用P1.3口

FS_O。

FS_L。

//初始化红外发射端口

P2DIR=0xff。

P2OUT=0xff。

//初始化LED端口

LCD_INIT(>。

//初始化液晶

TACTL|=TASSEL_2+MC_1+TACLR。

//设置定时器A时钟源为MCLK,不分频,增计数模式

TACCTL0|=CCIE。

//允许比较0中断

TACCTL1|=CCIE。

//允许比较1中断

TACCR0=210。

//26.25us中断一次,用以产生38kHZ,占空比为1:

3的方波

TACCR1=70。

//8.75us中断一次

//_BIS_SR(GIE>。

_EINT(>。

//开启总中断

//_DINT(>。

//关闭总中断

for(。

>

{

infrared(>。

//红外接收检测

P1DIR=0x0f。

//红外接收和矩阵键盘端口复用,所以在调用键盘扫描程序前重定义端口

P1OUT=0x00。

keydata=key(>。

//读键值

if(keydata>//如果用按键按下,根据返回值调用发射相对的编码

switch(keydata>

{

case1:

IR_SEND(table_ir0>。

break。

//如果按下1,发射“音量-”

case2:

IR_SEND(table_ir1>。

break。

//如果按下2,发射“音量+”

case3:

IR_SEND(table_IR>。

break。

//如果按下3,发射上次红外接收的编码值

default:

break。

}

}

}

/*************红外发射函数***************/

voidIR_SEND(uchar*pir>

{

uchari。

width=383。

_EINT(>。

//开启总中断

while(width>0>。

//输出9ms的载波信号

_DINT(>。

//关闭总中断

FS_H。

delay_us(4500>。

//输出4.5ms的高电平

for(i=0。

i<32。

i++>

{

width=21。

//21

_EINT(>。

//开启总中断

while(width>0>。

//输出0.56ms的载波信号

_DINT(>。

//关闭总中断

if(*pir++>{FS_H。

delay_us(1685>。

}//根据编码确定要输出“0”还是“1”

else{FS_H。

delay_us(560>。

}//如果是“1”输出1.685ms的高电平,

}//如果是“0”,输出0.56ms的高电平

width=21。

//21

_EINT(>。

//开启总中断

while(width>0>。

//输出0.56ms的载波信号作为结束码

_DINT(>。

//关闭总中断

FS_L。

//关闭红外发射管

P2OUT&=~BIT0。

delay_ms(100>。

P2OUT|=BIT0。

//LED0闪烁一下作为发射标志

}

/*************红外接收函数***************/

voidinfrared(void>

{

uchark。

ucharir=0。

ucharj=0。

ucharvalue_L=0,value_H=0。

//存放操作码的高四位和低四位

HW_I。

//在检测前把端口为输入

for(k=0。

k<19。

k++>

{

delay_us(400>。

if(HW_Q>{return。

}//检测是否有9ms的低电平,否则返回重新检测

}

while(!

HW_Q>。

//等待9ms低电平过去

for(k=0。

k<5。

k++>

{

delay_us(500>。

if(!

HW_Q>{return。

}//如果在2.5ms内有低电平,则认为是干扰,并且退出重新检测

}

while(HW_Q>。

//等待4.5ms高电平过去

for(k=0。

k<42。

k++>

{

while(!

HW_Q>。

//等待0.565ms的低电平过去

while(HW_Q>//计算高电平的宽度,判断接收的为“0”还是“1”

{

delay_us(100>。

j++。

if(j>22>{break。

}//如果高电平时间过长,跳出循环,继续执行下面的程序

}

if(j>=7>//如果高电平的宽度大于0.7ms,则接收的为1,同时存入数组

{

table_IR[k]=1。

}

elsetable_IR[k]=0。

//如果高电平宽度小于0.7ms,则接收的为“0”,同时存入数组

j=0。

}

for(k=16。

k<20。

k++>//把第3个字节低四位存入value_L内,便于在液晶上显示

{

value_L<<=1。

if(table_IR[k]>

value_L|=0x01。

}

for(k=20。

k<24。

k++>//把第3个字节高四位存入value_H内,便于在液晶上显示

{

value_H<<=1。

if(table_IR[k]>

value_H|=0x01。

}

WRITE_COM(0x80>。

//设置液晶第一行显示前16位字符<用户识别码)

while(READ_BF(>>。

for(k=0。

k<16。

k++>

{

ir=table_IR[k]。

WRITE_DATA(table_lcd[ir]>。

}

while(READ_BF(>>。

WRITE_COM(0x90>。

//设置液晶第二行显示8位的操作码和8位的操作反码

while(READ_BF(>>。

for(k=0。

k<16。

k++>

{

ir=table_IR[k+16]。

WRITE_DATA(table_lcd[ir]>。

}

while(READ_BF(>>。

WRITE_COM(0x88>。

//如果遥控器发出的是42位二进制码,则剩余的部分在第三行显示

while(READ_BF(>>。

for(k=0。

k<10。

k++>

{

ir=table_IR[k+32]。

WRITE_DATA(table_lcd[ir]>。

}

while(READ_BF(>>。

WRITE_COM(0x98>。

//第四行显示16进制的操作码

while(READ_BF(>>。

WRITE_DATA(table_lcd[value_L]>。

WRITE_DATA(table_lcd[value_H]>。

HW_O。

BUZ_ON。

delay_ms(50>。

BUZ_OFF。

}

/***********矩阵键盘检测函数,根据返回值可以判断按下的是哪个键***********/

unsignedcharkey(void>

{

unsignedcharrank。

charrow。

unsignedchartemp。

unsignedcharnum=0。

if((P1IN&0xf0>!

=0xf0>

{

delay_ms(15>。

if((P1IN&0xf0>!

=0xf0>

{

switch(P1IN&0xf0>//列检测

{

case0x70:

rank=0。

break。

case0xb0:

rank=4。

break。

case0xd0:

rank=8。

break。

case0xe0:

rank=12。

break。

}

temp=0x01。

for(row=4。

row>0。

row-->

{

P1OUT=~temp。

if((P1IN&0xf0>!

=0xf0>

{

num=row+rank。

P1OUT=0xf0。

returnnum。

}

temp<<=1。

}

while((P1IN&0xf0>!

=0xf0>。

delay_ms(15>。

while((P1IN&0xf0>!

=0xf0>。

}

}

returnnum。

}

/**************液晶初始化函数**************/

voidLCD_INIT(void>

{

P5OUT|=RST。

P5OUT|=PSB。

WRITE_COM(0x30>。

while(READ_BF(>>。

WRITE_COM(0x0c>。

while(READ_BF(>>。

WRITE_COM(0x01>。

while(READ_BF(>>。

}

/***************液晶写指令函数**************/

voidWRITE_COM(ucharcom>

{

P5OUT&=~RS。

P5OUT&=~RW。

P5OUT&=~EC。

P4OUT=com。

delay_us(5>。

P5OUT|=EC。

delay_us(5>。

P5OUT&=~EC。

}

/**************液晶写数据函数**************/

voidWRITE_DATA(uchardata>

{

P5OUT|=RS。

P5OUT&=~RW。

P5OUT&=~EC。

P4OUT=data。

delay_us(5>。

P5OUT|=EC。

delay_us(5>。

P5OUT&=~EC。

}

/*************液晶忙检测函数*************/

charREAD_BF(void>

{

ucharbusy。

P4DIR=0x00。

P5OUT&=~RS。

P5OUT|=RW。

P5OUT|=EC。

busy=P4IN。

delay_us(5>。

P5OUT&=~EC。

P4DIR=0xff。

return(busy&0x80>。

}

/**************定时器A中断服务函数,通过对红外发射端口置位和复位,实现占空比1:

3的PWM调制信号**************/

#pragmavector=TIMERA0_VECTOR

__interruptvoidtimeA_0(void>

{

width--。

FS_H。

}

#pragmavector=TIMERA1_VECTOR

__interruptvoidtimeA_1(void>

{

FS_L。

TACCTL1&=~CCIFG。

}

#pragmavector=PORT1_VECTOR

__interruptvoidport1(void>

{

//P1IFG&=~BIT3。

//flag=1。

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1