前言
上一次做了接收遥控红外信号的小试验,这一次尝试分析一下,找一下规律,尝试模拟这个信号,实现对空调的控制
文章目录
一、接收多次信号分析
拿遥控对着自己制作的红外接收器按下几次开关键,接收到的数据如下
数据有很多,就不全部贴出来了,就说一下我所发现的规律。可能不准确,仅供参考
1、 遥控的开关键,对应两种不同的红外信号,在不同的温度下开关机,按开关键发送的红外信号不同。
2、 按下温度+(或-)键,记录每个温度值对应的红外信号,之后按一下 开关键,又按温度+(或-)键,记录每个温度值对应的红外信号,发现温度+(-)也对应着两种信号,在温度值对应的红外信号里有之前按开关键的红外信号,说明遥控的开关、加减键发送的其实是一个温度设定信号,只不过有两种。
3、 其他的我也说不上来,感兴趣的可以自己试一下
二、代码
初步了解了那些信号之后,就可以尝试模拟了,首先我们需要一个定时器来产生频率为38kHZ的PWM信号,代码如下
TIM3_PB5_PWM_Init(377,4); // 72M/((377+1)*(4+1)) ≈ 38kHZ
//TIM3 PB5
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PB5_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5
//设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOB.5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
//初始化TIM3
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
//初始化TIM3 Channel2 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1,计数值<自动重装载值时,输出高电平
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIM3
}
初始化好定时器之后,我们就可以通过TIM_SetCompare2(TIM3,*)来控制红外信号了。
首先是引导码
//发送引导码
void Send_guide_code(void)
{
TIM_SetCompare2(TIM3,188); //发射端发射38khz红外信号,接收端接收的是低电平
delay_ms(8);
delay_us(500);
TIM_SetCompare2(TIM3,0);
delay_ms(4);
delay_us(200);
}
然后是发送0,1,一个字节
//发送n次0
void Send_ntimes_0(u8 n)
{
int i;
for(i=0;i<n;i++)
{
TIM_SetCompare2(TIM3,188);
delay_us(570);
TIM_SetCompare2(TIM3,0);
delay_us(520);
}
}
//发送n次1
void Send_ntimes_1(u8 n)
{
int i;
for(i=0;i<n;i++)
{
TIM_SetCompare2(TIM3,188);
delay_us(570);
TIM_SetCompare2(TIM3,0);
delay_us(1620);
}
}
//发一个送字节
void Send_Byte(u8 data)
{
int rec;
for(rec=7;rec>=0;rec--)
{
if(data & (1<<rec))
{
Send_ntimes_1(1);
}
else
{
Send_ntimes_0(1);
}
}
}
有了这些之后,我们就可以根据之前的分析来模拟红外信号了,这里我把制冷模式的开机信号Power_cold_1(Power_cold_2)单独拿了出来,其实可以直接用set_cold_tmp1(或set_cold_tmp2)来制冷模式开机,用set_hot_tmp1(set_hot_tmp2)来制暖模式开机。
void Power_cold_1(void)
{
Send_guide_code();
Send_Byte(0x6A);
Send_Byte(0x1E);
Send_ntimes_0(21);
Send_ntimes_1(1);
Send_ntimes_0(8);
Send_ntimes_1(2);
Send_ntimes_0(64);
Send_Byte(0x14);
TIM_SetCompare2(TIM3,188);
delay_us(590);
TIM_SetCompare2(TIM3,0);
}
void Power_cold_2(void)
{
Send_guide_code();
Send_Byte(0x6A);
Send_Byte(0x1E);
Send_ntimes_0(21);
Send_ntimes_1(1);
Send_ntimes_0(74);
Send_Byte(0x38);
TIM_SetCompare2(TIM3,188);
delay_us(590);
TIM_SetCompare2(TIM3,0);
}
void tmp_hot_1(u8 a,u8 b)
{
Send_guide_code();
Send_Byte(0x6A);
Send_Byte(a);
Send_ntimes_0(20);
Send_ntimes_1(1);
Send_ntimes_0(75);
Send_Byte(b);
TIM_SetCompare2(TIM3,188);
delay_us(590);
TIM_SetCompare2(TIM3,0);
}
void set_hot_tmp1(u8 tmp)
{
if(tmp>=16 && tmp<=20)
{
if(tmp == 16) tmp_hot_1(0x36,0x78);
else if(tmp == 17) tmp_hot_1(0xB6,0xF8);
else if(tmp == 18) tmp_hot_1(0x76,0x04);
else if(tmp == 19) tmp_hot_1(0xF6,0x84);
else if(tmp == 20) tmp_hot_1(0x0E,0xC8);
}
}
void tmp_hot_2(u8 a,u8 b)
{
Send_guide_code();
Send_Byte(0x6A);
Send_Byte(a);
Send_ntimes_0(20);
Send_ntimes_1(1);
Send_ntimes_0(9);
Send_ntimes_1(2);
Send_ntimes_0(64);
Send_Byte(b);
TIM_SetCompare2(TIM3,188);
delay_us(590);
TIM_SetCompare2(TIM3,0);
}
void set_hot_tmp2(u8 tmp)
{
if(tmp>=16 && tmp<=20)
{
if(tmp == 16) tmp_hot_2(0x36,0x54);
else if(tmp == 17) tmp_hot_2(0xB6,0xD4);
else if(tmp == 18) tmp_hot_2(0x76,0x34);
else if(tmp == 19) tmp_hot_2(0xF6,0xB4);
else if(tmp == 20) tmp_hot_2(0x0E,0xF8);
}
}
void tmp_cold_1(u8 a,u8 b)
{
Send_guide_code();
Send_Byte(0x6A);
Send_Byte(a);
Send_ntimes_0(21);
Send_ntimes_1(1);
Send_ntimes_0(74);
Send_Byte(b);
TIM_SetCompare2(TIM3,188);
delay_us(590);
TIM_SetCompare2(TIM3,0);
}
void tmp_cold_2(u8 a,u8 b)
{
Send_guide_code();
Send_Byte(0x6A);
Send_Byte(a);
Send_ntimes_0(21);
Send_ntimes_1(1);
Send_ntimes_0(8);
Send_ntimes_1(2);
Send_ntimes_0(64);
Send_Byte(b);
TIM_SetCompare2(TIM3,188);
delay_us(590);
TIM_SetCompare2(TIM3,0);
}
void set_cold_tmp1(u8 tmp)
{
if(tmp>=24 && tmp<=32)
{
if(tmp==24) tmp_cold_1(0x2E,0x18);
else if(tmp==25) tmp_cold_1(0xAE,0x98);
else if(tmp==26) tmp_cold_1(0x6E,0x58);
else if(tmp==27) tmp_cold_1(0xEE,0xD8);
else if(tmp==28) tmp_cold_1(0x1E,0x38);
else if(tmp==29) tmp_cold_1(0x9E,0xB8);
else if(tmp==30) tmp_cold_1(0x5E,0x78);
else if(tmp==31) tmp_cold_1(0xDE,0xF8);
else if(tmp==32) tmp_cold_1(0x3E,0x04);
}
}
void set_cold_tmp2(u8 tmp)
{
if(tmp>=24 && tmp<=32)
{
if(tmp==24) tmp_cold_1(0x2E,0x24);
else if(tmp==25) tmp_cold_1(0xAE,0xA4);
else if(tmp==26) tmp_cold_1(0x6E,0x64);
else if(tmp==27) tmp_cold_1(0xEE,0xE4);
else if(tmp==28) tmp_cold_1(0x1E,0x14);
else if(tmp==29) tmp_cold_1(0x9E,0x94);
else if(tmp==30) tmp_cold_1(0x5E,0x54);
else if(tmp==31) tmp_cold_1(0xDE,0xD4);
else if(tmp==32) tmp_cold_1(0x3E,0x34);
}
}
好,有了这些控制信号,就可以测试一下是否有用了,写个简单的main函数测试一下,当然首先需要搭建一个简单的发射电路
代码如下
int main(void)
{
int i;
u8 flag = 0;
USART_Config();
delay_init();
TIM3_PB5_PWM_Init(377,4); // 72M/(377+1)/(4+1) = 38.09khz
while(1)
{
for(i=0;i<10;i++)
{
delay_ms(1000);
}
if(!flag)
{
Power_cold_1(); // 10秒开关机一次
flag = 1;
}
else
{
Power_cold_2();
flag = 0;
}
}
}
测试空调成功开机!