|
wujinlin(VIP会员)
头衔:社区公民
帮派:无帮无派
帖数:26
金钱:380
积分:112
注册时间:2020/12/30
|
两路学习型风扇遥控开关带自然风 单片机源程序+电路图 电路原理图如下: 制作说明: 这个电路采用15W104单片机通过红外遥控器控制电风扇。 在初次使用时,首先进行按键学码。 学码方法:找一个闲置的红外遥控器,选择两个好用的按键,按住其中一个遥控 按键不放约6秒,蜂鸣器响一声,表明学习完成。同样方法学习另外一个遥控按键。 正常使用时,短按一下已学习的按键即可控制对应的开关反转,蜂鸣器会响一声。 第一个学习的按键为风扇开关,开后吹风3小时会自动关闭,防止长开。第二个学 习的按键为自然风开关,自然风启动后电扇吹7秒停3秒,再按关闭自然风。由于使用 延时控制,开自然风后遥控反应会延迟。 如果需要换别的遥控按键或另外一个遥控器,重新上述操作,即可删除旧的按键, 使用新的按键。 红外接收端为1脚。输出端为5脚,低电平为工作态。蜂鸣器接8脚,低电平为工作 态。 落地扇或台扇一般有3个档位,实际制作时可将其中一个档位改成遥控,另外两个 仍用手动。我是将最慢的1档改成了遥控。 电路图是借用别人的,程序也是应邀修改的,只要把8脚的led指示灯换成蜂鸣器即 可。当然不换也行,看各人爱好。程序不会冲突,指示灯和蜂鸣器都是低电平工作。 单片机源程序如下: #define CPU_Fosc 11059200uL //定义时钟,自适应解码和延时用 #include <REG51.h> #include<EROM_STC10_11_15.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int #define USER_H 0x80 //用户码高8位 #define USER_L 0x7F //用户码低8位 #define Check_EN 0 //是否要校验16位用户码:不校验填0,校验则填1 #define CA_S 40 //长按时间设置,单位:108mS(即 108mS整数倍,10倍以上为宜) /*┈┈┈┈┈┈┈┈┈┈ 基准 ┈┈┈┈┈┈┈┈┈┈┈*/ #define Boot_Limit (((9000+4500) +2000)/Step) //引导码周期上限 #define Boot_Lower (((9000+4500) -2000)/Step) //引导码周期下限 #define Bit1_Limit ((2250 +800)/Step) //“1”周期上限 #define Bit0_Limit ((1125 +400)/Step) //“0”周期上限 #define Step 400//红外采样步长:400us #define TH_H ((65536-Step*(CPU_Fosc/300)/40000)/256) //定时器高8位基准赋值 #define TH_L ((65536-Step*(CPU_Fosc/300)/40000)%256) //定时器低8位基准赋值 sfr P3M0 = 0xB2; //0000,0000 端口3模式寄存器0 sfr P3M1 = 0xB1; //0000,0000 端口3模式寄存器1 uint IR_BT; //解码效果返回:0无效,1有效,2短按,3长按 uchar NEC[4]; //解码存放:16位用户码、操作码正反码 uint cntCA; //长按计数 uint cntStep; //步数计 bit IRa,IRb; //电位状态保存 bit IRsync; //同步标志 bit bz1,bz2,bz3,bz4; bit m1,m2; //红外输入键值变量 uint BitN; //位码装载数 uchar num1,num2,num3,num4; uchar aa; float tm; /********************************************/ sbit out_1 = P3^0; //输出1 sbit BE = P3^3; //蜂鸣器 sbit IR = P3^4; //定义红外线接口(任意引脚) /************************************************/ //======================================================================== // 函数: void delayms(unsigned int ms) // 描述: 延时函数。 // 参数: ms,要延时的ms数, 这里只支持1~65535ms. 自动适应主时钟. // 返回: none. // 版本: VER1.0 // 日期: 2013-4-1 // 备注: //======================================================================== void DelayMs(unsigned int ms) { unsigned int i; do{ i = CPU_Fosc / 13000; while(--i) ; //14T per loop }while(--ms); } /****************蜂鸣器*************************/ void beep() { BE=0; DelayMs(500); BE=1; } /***************写数据 ***************************/ void W_W_1(void)//写数据 { num1 = NEC[2]; EA = 0; //关中断 EROM_C(0); //读擦除EPPROM EROM_W(0,5,num1); //写EPPROM num2 = EROM_R(0,5); //读EPPROM EA = 1; //开中断 } /**************写数据 ****************************/ void W_W_2(void)//写数据 { num3 = NEC[2]; EA = 0; //关中断 EROM_C(1); //读擦除EPPROM EROM_W(1,10,num3); //写EPPROM num4 = EROM_R(1,10); //读EPPROM EA = 1; //开中断 } /****************遥控短按处理*************************/ void KZ0()//函数:遥控短按处理 { beep(); num2 = EROM_R(0,5); //读EPPROM num4 = EROM_R(1,10); if(num2 == num1) { // bz3 = m1; // out_1 = ~out_1; m1=~m1; } if(num4 == num3) { m2=~m2; } } /*****************遥控长按处理********************/ void KZ1()//函数:遥控长按处理 { beep(); //m2 = 1; //m1 = 1; aa ++; if(aa == 1) { W_W_1();//读写程序 } if(aa == 2) { W_W_2();//读写程序 aa = 0; } } /****************红外解码初始化************************/ void IR_Init() //红外线解码初始化 { TMOD &= 0xF0; //清定时器0 TMOD |= 0x01; //定时器0:16位定时器 TL0 = TH_L; //每步时间 TH0 = TH_H; ET0 = 1; EA = 1; TR0 = 1; } /****************主函数*************************/ void main(void) { P3M0 = 0x03; // P3M1 = 0x00; // m1 = 0; m2 = 0; BE=1; IR_Init(); //红外线解码初始化 num2 = EROM_R(0,5); //读EPPROM num4 = EROM_R(1,10); //读EPPROM while(1) { if((IR_BT == 2) || (IR_BT == 3))//遥控检测 { tm=0; //有操作,开机时间清0 if(IR_BT == 2) KZ0(); //短按处理 else KZ1(); //长按处理 IR_BT = 0; //清有效标志 } if(tm>27000000) //风扇开启3小时后关闭(3*3600*1000000us/400us=27000000次) { m1=1; //风扇停电 tm=27000001; //停止计时防止溢出 } out_1=~m1; if(m1==1) { if(m2==1) { DelayMs(7000); //风扇通电7s out_1=1; DelayMs(3000); //风扇停电3s } } } } /********************** 定时器0中断函数************************/ void time0(void) interrupt 1 { TL0 = TH_L; //重赋值 TH0 = TH_H; IRb = IRa; //上次电位状态 IRa = IR; //当前电位状态 tm ++; cntStep ++; if(IR_BT == 1) if(cntStep > 300) IR_BT = 2;//解码有效后,如果无长按,120ms(400us×300)后默认短按 if(IRb && !IRa) //是否下降沿(上次高,当前低) { if(cntStep > Boot_Limit) //超过同步时间? { if(IR_BT == 1) //解码有效后,继续按住遥控>CA_S即长按 if(++ cntCA > CA_S) IR_BT = 3; IRsync = 0; //同步位清0 } else if(cntStep > Boot_Lower) { IRsync = 1; //同步位置1,装载位码数 BitN = 32; } else if(IRsync) //如果已同步 { if(cntStep > Bit1_Limit) IRsync = 0; else { NEC[3] >>= 1; if(cntStep > Bit0_Limit)NEC[3] |= 0x80; //“0”与“1” if(-- BitN == 0) { IRsync = 0; //同步位清0 #if (Check_EN == 1) if((NEC[0] == USER_H) && (NEC[1] == USER_L) && (NEC[2] == ~NEC[3])) //校验16位用户码、操作码正反码 { IR_BT = 1; //解码有效,接下来判断:短按?长按? cntCA = 0; } #else if(NEC[2] == ~NEC[3])//校验操作码正反码 { IR_BT = 1; cntCA = 0; } #endif } else if((BitN & 0x07) == 0)//NEC[3]每装满8位,移动保存一次(即 BitN%8 == 0) { NEC[0] = NEC[1]; NEC[1] = NEC[2]; NEC[2] = NEC[3]; } } } cntStep = 0; //步数计清0 } /******************************************/ if(IR_BT == 1)//写键值指示 { num1 = NEC[2]; } /*****************************************/ if(IR_BT == 1)//写键值指示 { num3 = NEC[2]; } } 这家伙很懒,什么也没有留下! |
等级: |
2020/12/30 22:11:19
|