4 7
您的位置: 电子制作DIY -> 单片机 -> 51单片机 -> 两路学习型风扇遥控开关带自然风 单片机源程... 
本帖共有620个阅读者
发表帖子 发表投票 回复主题
两路学习型风扇遥控开关带自然风 单片机源程序+电路图
尊贵身份标志
wujinlin(VIP会员)
wujinlin
头衔:社区公民
帮派:无帮无派
帖数:26
金钱:380
积分:112
注册时间:2020/12/30
楼主信息 | 留言 | Email | 主页 | 编辑 | 管理 | 离线
两路学习型风扇遥控开关带自然风 单片机源程序+电路图
电路原理图如下:
制作说明:
    这个电路采用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];
}
}




这家伙很懒,什么也没有留下!
等级:VIP会员 参考IP地址:*.*.*.*
2020/12/30 22:11:19
Copyright © 2011 电子制作DIY. All rights reserved.电子制作DIY8012 Call, 1 Queries, Processed in 122.070 millisecond(2),