本帖最后由 danieldan007 于 2016-1-16 12:04 编辑
最近在做一个自制红外遥控器,想控制空调(现在只能用这个做试验),所用单片机为CC2530,红外发射管为VS838,原理图如下:
其中P1_7输入38kHz,占空比为1/3的方波,P1_6通过输入0/1来控制电路的通断。最下面的“1”和“2”分别插入发射管的两个引脚。
空调是一般的格力挂式空调,遥控器型号为YB0FB2,已经确定它采用的是NEC格式的红外发射芯片,如图:
N编NEC的编码格式为[size=13.3333px]:
引导码:9ms 的载波+4.5ms 的空闲。
· 比特值“0”:560us 的载波+560us 的空闲。 · 比特值“1”:560us 的载波+1.68ms 的空闲。 以下是我所写的程序: #include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
#define LED1 P1_6
uint count = 0;
uint count1 = 0;
uint endcount = 0;
uint flag = 0;
void T3_Init()
{
//T3产生38khz的载波,周期为26us P1_7通道1,备用位置2
PERCFG |= 0x20;//T3备用位置2
T3CTL |= 0X0B;//0分频,选择PWM模式,即成16M,周期为0.0625us,关T3,发送引导码时开T3;开溢出,PWM
//0101 1100 开中断,compare-up,比较模式
T3CCTL1 |= 0X1C;
T3CCTL0 |= 0x1C;
//占空比1/3
T3CC0 |= 210;//202;
T3CC1 |= 140;//136;//140;
P1SEL |= 0X80;//P1_7做外设使用
P1DIR |= 0Xc0;//P1_6 P1_7输出
}
void T1_Init()
{
T1CTL |= 0X0C;//32M,128分频,周期4us,暂停模式,发送数据时设模模式
T1CTL |= 0x02;
T1STAT |= 0X21;//设溢出标志位
T1CCTL0 |= 0x04;
T1CC0L = 0x02;
T1CC0H = 0x00;
IRCON &= ~0x02;
T1IE = 1;//开T1中断使能
EA = 1;
}
void Led_Init()
{
P1DIR |= 0X40;
P1_6 = 0;
}
void Delay_ms(uint time)
{
uint i,j;
for (i=time; i>0; i--)
for (j=1774; j>0; j--)
;
}
void Begining()
{
T3CTL |= 0X10;//开T3
}
void Counter_Delay(uint temp1, uint temp2)
{
endcount = temp1;
flag = temp2;
count1 = 0;
while(1)
{
// EA = 0;
if(count1 < endcount)
EA = 1;
else
{
EA = 1;
break;
}
}
}
void SendIRData_BYTE(uint irdata, uint num)
{
uint i;
for(i = 0; i < num; i++)
{
Counter_Delay(23, 1); //延时560us
if(irdata & 0x01)
Counter_Delay(69, 0); //延时1640us
else
Counter_Delay(23, 0);
irdata = irdata >> 1;
}
}
//前导码
void Preamble(void)
{
Counter_Delay(375, 1); //延时9ms
Counter_Delay(187, 0); //延时4.5ms
}
void main(void)
{
//32MHz XOSC
CLKCONCMD &= 0XBF; //1010 1111
while (CLKCONSTA & 0X40)
;
T3_Init();
T1_Init();
Begining();
Led_Init();
while (1)
{
Preamble();
SendIRData_BYTE(0x04, 8);
SendIRData_BYTE(0x0E, 8);
SendIRData_BYTE(0x20, 8);
SendIRData_BYTE(0x50, 8);
SendIRData_BYTE(0x02, 3);
//20ms
Counter_Delay(23, 1);
Counter_Delay(833, 0);
SendIRData_BYTE(0x00, 8);
SendIRData_BYTE(0x20, 8);
SendIRData_BYTE(0x00, 8);
SendIRData_BYTE(0xE0, 8);
Counter_Delay(23, 1);
Counter_Delay(8330, 0);
}
}
#pragma vector = T1_VECTOR
__interrupt void T1_ISR(void)
{
count1++;
if ((T1STAT & 0x01) > 0)//判断IRCON的bit1
{
T1STAT &= ~0x01;//清除中断标志
if (flag)
{
LED1 = 0;
}
else
LED1 = 1;
}
之前用的延时做的,后来我同学说延时不准确,建议用定时器,后来写了这个定时器的程序,结果还是不行,郁闷。 里面的编码都是我通过红外接收在示波器上看到的波形来判断出来的,基本不会有问题,格力空调的编码为“前导码+35位数据+间隔+32位数据”组成。 现在的问题就是,虽然波形与遥控器通过红外接收管产生的波形相同,但是脉宽却不尽相同,前后相差几十us,(比如我发的是560us,在P1_6测得的宽度是560us,经过载波以后有时候是500us有时候是600us还有时候正好是560us)根据NEC编码的协议来写的程序测得P1_6口的脉宽很稳定,但是经过载波之后的脉宽不是很稳定,有时候大有时候小,不知这是否属于正常现象。我用遥控器测得的脉宽就相对稳定一些。现在我用我的编码将发射管对准空调一点反应也没有,是否和这个脉冲宽度的调节有关?还是说我上面做的那个方面有问题?还请以前做过相关方面的指点一下,万分感谢呀! 下面这个是我将示波器的两个探头一个连在发射管上,一个连在接收管上得到的波形中的一段,还请大家帮我看一下这个波形是否正常,谢谢! 另外如果在以前做过红外方面有什么心得欢迎指教一下呀,我现在真是一点思路都没有了!
|