发布时间:2025-12-09 11:43:47 浏览次数:2
我们家里的空调、电视等,它们的遥控器都是通过红外信号来控制的。其实,我们可以自己用红外发射模块来做一个遥控器。
关于红外的知识,大家可以参考我之前的文章:基于红外传输的多点温度采集系统,这里就不再赘述了。
要自己实现红外遥控器的功能,思路其实很简单,首先,我们需要知道原来遥控器发射的信号是怎么样的,然后我们只要用红外发射模块发射一个一模一样的信号就行了。
实验器材准备:
红外接收模块、红外发射模块、逻辑分析仪。
一、获取遥控器的波形
我们使用红外接收模块,连上逻辑分析仪,然后使用空调遥控器对着红外接收模块发射信号,这时逻辑分析仪就采集到了红外信号。这一部分不需要什么代码。
这是我用逻辑分析仪采集到格力空调按下“打开”按钮时的波形。
分析一下波形,可以知道,先是有一段约9ms的低电平,然后是4.5ms的高电平,再是一段0 1构成的序列,中间是20.5ms的高电平,再经过一段序列结束。
那些序列就是真正的信号,里面有控制空调的相关信息,当然,不同的空调肯定是不一样的,这是厂家定义的。
二、用单片机产生红外信号
知道了遥控器发射的波形,我们不需要去理解它是什么含义,只要照着来发射一段相同的波形,就能实现功能。
这里就是要稍微注意一下红外信号的特点,这在我之前的文章里有详细讲过,这里再说一下:
对于红外信号来说,当你发射一段脉冲时(脉冲频率通常是38khz),红外接收端收到的是低电平,否则,收到的是高电平。
也就是说,你如果希望接收端收到的是低电平,你不是要发射低电平,而是发射一段脉冲。比如上面最开始是9ms的低电平,那么你需要发射一段持续9ms的脉冲。
还有就是逻辑0是一段低电平加上一段不长的高电平,逻辑1是一段低电平加上一段较长的高电平。在这里,0是0.62ms低电平+0.56ms高电平,1是0.65ms低电平+1.7ms高电平。
首先我们把上面的序列保存在数组里面,因为中间有一段较长的高电平时间,所以把它分成两段来保存。
char open_1[]={1,0,0,1,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,1,0,0};char open_2[]={1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1};char close_1[]={1,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,1,0,0};char close_2[]={1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0};然后我们把发送逻辑1或者逻辑0封装成函数
//发送红外格式的1或者0。1:0.65ms高电平+1.67ms低电平 0:0.56ms低电平+0.55ms高电平void sendData(int n){ if(n==0) { endcount=t(650-100); //理论计算与实际有偏差,需要进行一定的修正 flag=1; //表示需要发送低电平,体现为一段脉冲 count=0; while(count<endcount); endcount=t(550); flag=0; count=0; while(count<endcount); } else{ endcount=t(650-70); flag=1; //表示需要发送低电平,体现为一段脉冲 count=0; while(count<endcount); endcount=t(1600); flag=0; count=0; while(count<endcount); }}把发送一段长时间的高电平或者低电平封装成函数
//发送普通的电平,电平1或者电平0,第二个参数是由上面的宏定义得到void sendUsrLevel(int level,int t){ endcount=t; count=0; if(level==0) { flag=1; } else{ flag=0; } while(count<endcount);}最后调用上面的函数把控制空调的信号发射出去
//控制空调的开或者关,0:关闭空调,1:开启空调void ControlAirConditioner(int cmd){ char len=0; sendUsrLevel(0,t(9000-600)); //理论计算与实际有偏差,需要进行一定的修正 sendUsrLevel(1,t(4500-350)); if(cmd==0) //关闭空调 { len=sizeof(open_1)/sizeof(open_1[0]); for(int i=0;i<len;i++) //发送第一段数据 { sendData(open_1[i]); } sendUsrLevel(1,t(20600-2000)); len=sizeof(open_2)/sizeof(open_2[0]); for(int i=0;i<len;i++) //发送第二段数据 { sendData(open_2[i]); } } else{ //打开空调 len=sizeof(close_1)/sizeof(close_1[0]); for(int i=0;i<len;i++) //发送第一段数据 { sendData(close_1[i]); } sendUsrLevel(1,t(20600-2000)); len=sizeof(close_2)/sizeof(close_2[0]); for(int i=0;i<len;i++) //发送第一段数据 { sendData(close_2[i]); } }}在main函数中进行调用,通过按键来控制空调的开或者关
int main(){ u8 i,ret=0; count = 0; flag = 0; OP = 0; IR_OUT = 1; SysTick_Init(72); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2组 LED_Init(); KEY_Init(); TIM4_Init(13,72-1); //定时13us while(1) { i++; if(i%20==0) { led1=!led1; }// delay_ms(1000); ret=KEY_Scan(0); if(ret==KEY_LEFT) { ControlAirConditioner(1); //开空调// sendUsrLevel(0,t(9000));// sendUsrLevel(1,t(4500)); } if(ret==KEY_RIGHT) { ControlAirConditioner(0); //关空调 } }}经过实际测试,确实可以控制我们的空调。
总的来说,思路比较简单,就是捕获遥控器的信号,这个作为标准信号,然后使用红外发射模块发射一个和他一样的信号,另外就是这个需要使用逻辑分析仪去好好分析你实际产生的波形和标准波形的偏差,理论计算与实际难免有误差。