红外遥控用PWM模拟38KHZ
这是以前MSP430F149定时器A写的
参考下
/*****************************************************
程序功能:用定时器TIME-A在向上模式下,输出模式为MODE3
P1.2脚输出一方波,方波周期频率为f=4MHZ/106=37.74KHZ,时长T=1/4MHZ * CCR0 = 26.5us,CCR0=106
为减小功耗,占空比1/3,高电平时长为9us,低电平时长为17.5us,CCR1=106*2/3=70
模式说明:向上模式,TAR=0,计数到CCR0,打开CCR0,CCR1,CCR2比较器功能,
打开P1.2,P1.3引脚的比较输出功能,在输出模式6中-翻转/置位,TAR计数与CCR1值相同时,
P1.2(TA1)引脚输出置1,TAR继续计数到CCR1时,转向下递减,减到CCR0值时,P1.2(TA0)引脚输出翻转置0,TAR继续递减到0
再重复循环
P1.3(TA2)同样
DCO频率为1000KHZ
------------------------------------------------------
注:模式6-翻转/置位,输出波形刚好相反
------------------------------------------------------
遥控编码波形(NEC-UPD6121G)
* ________________ __ __ __
* | | | | | |
* | | | | | |
* | | | | | |
* | | | | | |
* | | | | | |.....................................
* | | | | | |
* | | | | | |
* |________| |_| |__| "0"高:0.56ms+低:0.565ms=1.125ms
* |<- 9ms ->|<-4.5ms>|"0"| "1"| "1"高:0.56ms+低:1.69ms =2.25ms
* |<- 引导码 ->|<-起始码|<-8位地址->|<-地址反码->|8位数据->|<-数据反码->|
340周期
UPD6121G格式发码时长108ms,结束
******************************************************/
#include <msp430x14x.h>
#include "BoardConfig.h"
#include "cry1602.h"
uint ir_time,ir_time1;
uchar flag,flag2;
/****************************
TAR_CCRx初始化
****************************/
void TAR_init()
{
ir_time = 0;
ir_time1 = 0;
CCR0 = 106; //计数到CCR1置位高电平时长为(1/1000000)*(26-17)*2=0.05S
CCR1 = 70;
TACTL |= TASSEL_2 + ID_1 + MC_1; //定时时钟SMCLK=8000000hz,2分频,向上模式
CCTL0 |= CCIE; //充许CCR0中断
}
/********************************************************
函数名称:IR_37_6KHZ(uchar time)
输入参数:uchar time
输出参数:
函数功能:P1.2引脚输出频率为37.6KHZ频率的方波
高电平时长为9us,低电平时长为17.5us
time为P1.2引脚输出37.6KHZ频率方波的时长
********************************************************/
void IR_37_6KHZ(uint time)
{
CCTL1 = OUTMOD_3; // CCR1设置,输出模式3-输出状态翻转/置位,充许中断
flag = 1; //CCR0周期计数开始,一个周期为26.5us
while(ir_time < time) //判断输出时间是否到,没到继续输出IR信号
{
CCTL1 = OUTMOD_3;
}
ir_time = 0; //时间到计数清0
flag = 0; //退出计数
}
/********************************************************
函数名称:IR_low(uchar time)
输入参数:uchar time
输出参数:
函数功能:P1.2引脚输出频低电平
time为P1.2引脚输出低电平的时长
********************************************************/
void IR_low(uint time1)
{
CCTL1 = OUTMOD_0; // CCR1设置,输出模式0-输出状低电平
flag = 1; //CCR0周期计数开始,一个周期为26.5us
while(ir_time < time1) //判断输出时间是否到,没到继续输出低电平信号
{
CCTL1 = OUTMOD_0;
}
ir_time = 0; //时间到计数清0
flag = 0; //退出计数
}
/******************************************
函数名称:fama8(uchar dat)
输入参数:uchar dat
输出参数:
函数功能:P1.2引脚输出IR信号
低位首发,
******************************************/
void fama8(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
if(dat & 0x01)
{
IR_37_6KHZ(21); //红外逻辑1,高550us,低-1700us
IR_low(64);
}
else
{
IR_37_6KHZ(21); //红外逻辑0,高550us,低-550us
IR_low(21);
}
dat = dat >> 1;
}
}
void IR_6121G(uchar yonghu1,uchar yonghu2,uchar dat)
{
flag2 = 1; //CCR0周期计数开始,一个周期为26.5us
IR_37_6KHZ(339); //引导码 高9ms,低4.5ms
IR_low(169);
fama8(yonghu1); //低8位用户码
fama8(yonghu2); //高8位用户码
fama8(dat); //键值码
fama8(~dat); //键值反码
IR_37_6KHZ(21); //数据发完后,发一时长为550us红外高
while(ir_time1 < 4075) //判断108ms是否到,没到继续输出低电平信号
{
CCTL1 = OUTMOD_0;
}
ir_time1 = 0; //时间到计数清0
flag2 = 0; //退出计数
IR_37_6KHZ(339); //结束码 高9ms,低2.25ms
IR_low(85);
IR_37_6KHZ(21); //数据发完后,发一时长为550us红外高
}
void main()
{
uchar i;
WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗
BoardConfig(0xb0); // 关闭数码管、流水灯和电平转换
BCSCTL1 &= ~XT2OFF; //检测XT2失效
do
{
IFG1 &= ~OFIFG; //清除振荡器失效标志
for (i = 255; i>0; i--); //稳定时间
}
while ((IFG1 & OFIFG) != 0);
BCSCTL2 |= DIVM_1 + SELS + DIVS_1; //MCLK为XT2频率,2分频,4MHZ,SMCLK选XT2频率,2分频SMCLK=4MHZ
P1DIR = 0x07;
P1SEL = 0x07;
TAR_init(); //初始化定时器A
_EINT();
while(1)
{
IR_low(500);
IR_6121G(0x40,0xbf,0x01); //
IR_low(500);
}
}
/***********************
CCR0中断函数入口地址
***********************/
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0 (void)
{
if(flag)
{ir_time += 1;}
if(flag2)
{ir_time1 += 1;}
}
|