找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5367|回复: 17
打印 上一主题 下一主题
收起左侧

两路学习型风扇遥控开关带自然风 单片机源程序+电路

  [复制链接]
跳转到指定楼层
楼主
电路原理图如下:

制作说明:
    这个电路采用15W104单片机通过红外遥控器控制电风扇。
    在初次使用时,首先进行按键学码。
    学码方法:找一个闲置的红外遥控器,选择两个好用的按键,按住其中一个遥控
按键不放约6秒,蜂鸣器响一声,表明学习完成。同样方法学习另外一个遥控按键。
    正常使用时,短按一下已学习的按键即可控制对应的开关反转,蜂鸣器会响一声。
    第一个学习的按键为风扇开关,开后吹风3小时会自动关闭,防止长开。第二个学
习的按键为自然风开关,自然风启动后电扇吹7秒停3秒,再按关闭自然风。由于使用
延时控制,开自然风后遥控反应会延迟。
    如果需要换别的遥控按键或另外一个遥控器,重新上述操作,即可删除旧的按键,
使用新的按键。
        红外接收端为1脚。输出端为5脚,低电平为工作态。蜂鸣器接8脚,低电平为工作
态。
    落地扇或台扇一般有3个档位,实际制作时可将其中一个档位改成遥控,另外两个
仍用手动。我是将最慢的1档改成了遥控。
    电路图是借用别人的,程序也是应邀修改的,只要把8脚的led指示灯换成蜂鸣器即
可。当然不换也行,看各人爱好。程序不会冲突,指示灯和蜂鸣器都是低电平工作。

单片机源程序如下:
  1. #define CPU_Fosc 11059200uL //定义时钟,自适应解码和延时用
  2. #include <REG51.h>
  3. #include<EROM_STC10_11_15.h>
  4. #include<intrins.h>
  5. #define uchar unsigned char
  6. #define uint  unsigned  int
  7. #define USER_H     0x80  //用户码高8位
  8. #define USER_L     0x7F  //用户码低8位
  9. #define Check_EN   0   //是否要校验16位用户码:不校验填0,校验则填1
  10. #define CA_S       40   //长按时间设置,单位:108mS(即 108mS整数倍,10倍以上为宜)
  11. /*┈┈┈┈┈┈┈┈┈┈ 基准 ┈┈┈┈┈┈┈┈┈┈┈*/
  12. #define  Boot_Limit     (((9000+4500) +2000)/Step)   //引导码周期上限   
  13. #define  Boot_Lower     (((9000+4500) -2000)/Step)   //引导码周期下限   
  14. #define  Bit1_Limit     ((2250 +800)/Step)           //“1”周期上限
  15. #define  Bit0_Limit     ((1125 +400)/Step)     //“0”周期上限
  16. #define  Step       400//红外采样步长:400us
  17. #define  TH_H  ((65536-Step*(CPU_Fosc/300)/40000)/256)  //定时器高8位基准赋值
  18. #define  TH_L  ((65536-Step*(CPU_Fosc/300)/40000)%256)  //定时器低8位基准赋值
  19. sfr P3M0        =   0xB2;   //0000,0000 端口3模式寄存器0
  20. sfr P3M1        =   0xB1;   //0000,0000 端口3模式寄存器1
  21. uint     IR_BT;           //解码效果返回:0无效,1有效,2短按,3长按
  22. uchar    NEC[4];       //解码存放:16位用户码、操作码正反码
  23. uint     cntCA;           //长按计数
  24. uint     cntStep;    //步数计
  25. bit      IRa,IRb;    //电位状态保存
  26. bit      IRsync;    //同步标志
  27. bit      bz1,bz2,bz3,bz4;
  28. bit      m1,m2;     //红外输入键值变量
  29. uint     BitN;               //位码装载数
  30. uchar    num1,num2,num3,num4;
  31. uchar  aa;
  32. float   tm;
  33. /********************************************/
  34. sbit  out_1  = P3^0;   //输出1
  35. sbit  BE  = P3^3;   //蜂鸣器
  36. sbit  IR     = P3^4;    //定义红外线接口(任意引脚)
  37. /************************************************/
  38. //========================================================================
  39. // 函数: void  delayms(unsigned int ms)
  40. // 描述: 延时函数。
  41. // 参数: ms,要延时的ms数, 这里只支持1~65535ms. 自动适应主时钟.
  42. // 返回: none.
  43. // 版本: VER1.0
  44. // 日期: 2013-4-1
  45. // 备注:
  46. //========================================================================
  47. void  DelayMs(unsigned int ms)
  48. {
  49.      unsigned int i;
  50.          do{
  51.               i = CPU_Fosc / 13000;
  52.                   while(--i)        ;   //14T per loop
  53.      }while(--ms);
  54. }

  55. /****************蜂鸣器*************************/
  56. void beep()
  57. {
  58. BE=0;
  59. DelayMs(500);
  60. BE=1;
  61. }

  62. /***************写数据 ***************************/

  63. void W_W_1(void)//写数据
  64. {
  65. num1 = NEC[2];
  66. EA = 0;     //关中断
  67. EROM_C(0);    //读擦除EPPROM
  68. EROM_W(0,5,num1); //写EPPROM
  69. num2 = EROM_R(0,5); //读EPPROM
  70. EA = 1;  //开中断
  71. }

  72. /**************写数据 ****************************/

  73. void W_W_2(void)//写数据
  74. {
  75. num3 = NEC[2];
  76. EA = 0;     //关中断
  77. EROM_C(1);    //读擦除EPPROM
  78. EROM_W(1,10,num3); //写EPPROM
  79. num4 = EROM_R(1,10); //读EPPROM
  80. EA = 1;  //开中断
  81. }

  82. /****************遥控短按处理*************************/

  83. void KZ0()//函数:遥控短按处理
  84. {
  85.    beep();
  86. num2 = EROM_R(0,5); //读EPPROM
  87. num4 = EROM_R(1,10);
  88. if(num2 == num1)
  89. {
  90. //   bz3 = m1;
  91. //  out_1 = ~out_1;
  92.    m1=~m1;
  93. }
  94. if(num4 == num3)
  95. {
  96.    m2=~m2;
  97. }
  98. }

  99. /*****************遥控长按处理********************/

  100. void KZ1()//函数:遥控长按处理
  101. {
  102.   beep();
  103. //m2 = 1;
  104. //m1 = 1;
  105. aa ++;
  106. if(aa == 1)
  107. {
  108.   W_W_1();//读写程序
  109. }
  110. if(aa == 2)
  111. {
  112.   W_W_2();//读写程序
  113.   aa = 0;
  114. }
  115.   
  116. }
  117. /****************红外解码初始化************************/

  118. void IR_Init() //红外线解码初始化
  119. {
  120. TMOD &= 0xF0;    //清定时器0
  121. TMOD |= 0x01;    //定时器0:16位定时器
  122. TL0 = TH_L;        //每步时间
  123. TH0 = TH_H;
  124. ET0 = 1;
  125. EA  = 1;
  126. TR0 = 1;
  127. }

  128. /****************主函数*************************/
  129. void main(void)
  130. {
  131. P3M0 = 0x03;   //
  132. P3M1 = 0x00;   //
  133. m1 = 0;
  134. m2 = 0;
  135. BE=1;
  136. IR_Init();      //红外线解码初始化
  137. num2 = EROM_R(0,5); //读EPPROM
  138. num4 = EROM_R(1,10); //读EPPROM
  139. while(1)
  140. {
  141.   if((IR_BT == 2) || (IR_BT == 3))//遥控检测     
  142.   {
  143.    tm=0;                //有操作,开机时间清0
  144.    if(IR_BT == 2)
  145.     KZ0();      //短按处理   
  146.    else        
  147.     KZ1();      //长按处理
  148.     IR_BT = 0;  //清有效标志
  149.   }
  150.    if(tm>27000000)        //风扇开启3小时后关闭(3*3600*1000000us/400us=27000000次)
  151.     {
  152.      m1=1;                        //风扇停电
  153.      tm=27000001;   //停止计时防止溢出
  154.     }
  155.      out_1=~m1;
  156.          if(m1==1)
  157.           {
  158.            if(m2==1)
  159.             {
  160.              DelayMs(7000);          //风扇通电7s
  161.              out_1=1;
  162.              DelayMs(3000); //风扇停电3s
  163.                 }
  164.           }
  165. }
  166. }            
  167. /********************** 定时器0中断函数************************/
  168. void time0(void) interrupt 1
  169. {
  170. TL0 = TH_L;        //重赋值
  171. TH0 = TH_H;
  172. IRb = IRa;     //上次电位状态
  173. IRa = IR;     //当前电位状态
  174. tm ++;
  175. cntStep ++;     
  176. if(IR_BT == 1)
  177. if(cntStep > 300)
  178. IR_BT = 2;//解码有效后,如果无长按,120ms(400us×300)后默认短按
  179. if(IRb && !IRa)         //是否下降沿(上次高,当前低)
  180. {
  181.   if(cntStep > Boot_Limit)      //超过同步时间?
  182.   {
  183.       if(IR_BT == 1) //解码有效后,继续按住遥控>CA_S即长按
  184.    if(++ cntCA > CA_S)
  185.    IR_BT = 3;
  186.    IRsync = 0;      //同步位清0
  187.   }
  188.   else
  189.   if(cntStep > Boot_Lower)
  190.   {
  191.    IRsync = 1; //同步位置1,装载位码数
  192.    BitN = 32;
  193.   }     
  194.   else
  195.   if(IRsync) //如果已同步
  196.   {
  197.    if(cntStep > Bit1_Limit)
  198.    IRsync = 0;            
  199.    else
  200.    {
  201.     NEC[3] >>= 1;   
  202.     if(cntStep > Bit0_Limit)NEC[3] |= 0x80;    //“0”与“1”
  203.              if(-- BitN == 0)   
  204.     {
  205.      IRsync = 0;         //同步位清0
  206.               #if (Check_EN == 1)     
  207.      if((NEC[0] == USER_H) && (NEC[1] == USER_L) && (NEC[2] == ~NEC[3])) //校验16位用户码、操作码正反码
  208.       {  
  209.       IR_BT = 1; //解码有效,接下来判断:短按?长按?
  210.       cntCA = 0;  
  211.      }      
  212.      #else
  213.      if(NEC[2] == ~NEC[3])//校验操作码正反码
  214.      {
  215.       IR_BT = 1;
  216.       cntCA = 0;
  217.      }
  218.      #endif     
  219.     }
  220.     else
  221.     if((BitN & 0x07) == 0)//NEC[3]每装满8位,移动保存一次(即 BitN%8 == 0)
  222.     {
  223.      NEC[0] = NEC[1];
  224.      NEC[1] = NEC[2];
  225.      NEC[2] = NEC[3];   
  226.     }
  227.    }
  228.   }
  229.   cntStep = 0;   //步数计清0
  230. }   

  231. /******************************************/
  232. if(IR_BT == 1)//写键值指示
  233. {
  234.   num1 = NEC[2];
  235. }
  236. /*****************************************/
  237. if(IR_BT == 1)//写键值指示
  238. {
  239.   num3 = NEC[2];
  240. }
  241. }
复制代码

所有资料51hei提供下载:
两路学习型风扇遥控开关带自然风6.rar (51.48 KB, 下载次数: 146)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏13 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:17109 发表于 2019-8-30 16:36 | 只看该作者
师博你好;可以增加一只led灯用来学习状态显示吗
   
上电立即进入学习状态,红色LED灯闪动,用电视机或DVD遥控器对着红外接收器,按下其中任一按键发射信号,红色LED灯熄灭,蜂鸣器叫一声,表示学习成功。该按键会被自动识别对应使用。
在学习状态如果没有按下任何遥控器按键,10秒后自动退出学习状态
回复

使用道具 举报

板凳
ID:343102 发表于 2019-8-30 21:41 | 只看该作者
ll13536121668 发表于 2019-8-30 16:36
师博你好;可以增加一只led灯用来学习状态显示吗
   
上电立即进入学习状态,红色LED灯闪动,用电视机或D ...

你说的这些功能不是不能实现,只是个人感觉是画蛇添足意义不大。
首先,这个程序已经有按键提示了(蜂鸣器或led指示灯),再增加一个学习指示灯意义不大。在电源电路中增加一个电源指示灯,并与红外接收器放一起,用以给遥控器指示一个目标,这个都比学习指示灯更有意义。
其次,首次开机时必须学习按键,否则无法遥控。再增设一个10秒后自动退出学习状态功能就没有任何意义了,反而添乱。
这个程序在任何时候长按按键6S以上就会自动学习新按键,是非常实用的。
回复

使用道具 举报

地板
ID:17109 发表于 2019-8-31 06:20 来自手机 | 只看该作者
风158 发表于 2019-8-30 21:41
你说的这些功能不是不能实现,只是个人感觉是画蛇添足意义不大。
首先,这个程序已经有按键提示了(蜂鸣 ...

试过在6秒内学习前面没有提示,不知道根本不会使用还以为,程序有问题劰,加个LED提示就好
回复

使用道具 举报

5#
ID:416951 发表于 2019-9-1 23:12 | 只看该作者
谢谢分享
回复

使用道具 举报

6#
ID:34298 发表于 2019-10-20 16:00 | 只看该作者
这个更好 stc15w104是宽电压,可以用旧的手机电池供电,做个小型遥控器。
回复

使用道具 举报

7#
ID:616759 发表于 2019-10-28 14:45 | 只看该作者
这个电路图画的看的我有点懵逼,不知道附件里的原理图是不是也这样
回复

使用道具 举报

8#
ID:77927 发表于 2019-11-2 12:34 | 只看该作者

谢谢分享,学习学习
回复

使用道具 举报

9#
ID:77927 发表于 2019-11-2 12:47 | 只看该作者
文件打不开,.hex文件烧录软件都打不开
回复

使用道具 举报

10#
ID:51443 发表于 2020-2-4 21:08 | 只看该作者
本帖最后由 职教电子 于 2020-2-7 15:12 编辑

“ if(tm>27000000)        //风扇开启3小时后关闭(3*3600*1000000us/400us=27000000次)
    {
     m1=1;                        //风扇停电
     tm=27000001;   //停止计时防止溢出”
其中m1=1应该为m1=0.否则,3小时后不会停。另外把
#define  Boot_Limit     (((9000+4500) +2000)/Step)   //引导码周期上限   
#define  Boot_Lower     (((9000+4500) -2000)/Step)   //引导码周期下限
这两句改为
#define  Boot_Limit     (15500/Step)   //引导码周期上限
#define  Boot_Lower     (7000/Step)   //引导码周期下限  
能适合更多的遥控器使用。因为9012的引导码为4500+4500,7462的引导码是9000+4500.
回复

使用道具 举报

11#
ID:159575 发表于 2020-3-19 15:47 来自手机 | 只看该作者
这个只能用于nec编码的遥控器吧
回复

使用道具 举报

12#
ID:479492 发表于 2020-5-20 18:47 | 只看该作者
将程序下载到STC15W104的继电器控制板,按遥控器只有LED频闪,松开按键,LED灯熄灭。但继电器不会通断。不知是怎么回事。
回复

使用道具 举报

13#
ID:479492 发表于 2020-5-23 18:08 | 只看该作者
  为了知道自己遥控器的用户码,买了一个红外遥控器解码器,但即使将程序换成自己的用户码,还是不能读到遥控器。
   后来参考网上的方法,将程序里的频率改为12M,但Keil的设置频率及下载器频率按11.0592M,就可以读到部分遥控器,并能正常控制。
    但有部分遥控器不能读到:如有线电视机顶盒的遥控器、LED吸顶灯的遥控器等。
回复

使用道具 举报

14#
ID:479492 发表于 2020-12-16 11:36 | 只看该作者
后来,查了一下有线电视机顶盒的编码规范,并与NEC码进行了对比。如下图所示:

机顶盒与NEC对比1.png (214.09 KB, 下载次数: 46)

机顶盒与NEC对比1.png

8.PNG (238.48 KB, 下载次数: 49)

8.PNG

7.PNG (274.71 KB, 下载次数: 46)

7.PNG
回复

使用道具 举报

15#
ID:479492 发表于 2020-12-16 11:48 | 只看该作者
  按照机顶盒的编码规范,修改了楼主的一些参数(只接收前2个8位),结果原配的遥控器没有反应,但后来买的备用遥控器反而可以使用,但遥控机顶盒时,两个都能够正常使用的,并且,用读码器读到的两个遥控器的红外码是一样的。不知是什么原因?
  楼主可以按照机顶盒的编码,修改一下程序吗?谢谢!

WORD1.png (36.51 KB, 下载次数: 51)

WORD1.png

WORD2.png (12.65 KB, 下载次数: 49)

WORD2.png

WORD3.png (13.72 KB, 下载次数: 57)

WORD3.png

WORD4.png (15.79 KB, 下载次数: 49)

WORD4.png

WORD5.png (25.2 KB, 下载次数: 47)

WORD5.png

WORD6.png (7.55 KB, 下载次数: 50)

WORD6.png
回复

使用道具 举报

16#
ID:51443 发表于 2022-2-9 19:40 | 只看该作者
hq2000 发表于 2020-12-16 11:48
按照机顶盒的编码规范,修改了楼主的一些参数(只接收前2个8位),结果原配的遥控器没有反应,但后来买的 ...

原文中的NEC[3]是数据反码,改文中的NEC[1]是数据正码,运算结果不一样吧?
回复

使用道具 举报

17#
ID:403447 发表于 2023-8-11 11:51 | 只看该作者
虚心向大前辈们请教:EROM_W(1,5,num1)里,后面的num1是什么作用?与:EROM_W(1,5)结果有啥不同?
回复

使用道具 举报

18#
ID:403447 发表于 2023-8-14 09:10 | 只看该作者
大米861 发表于 2023-8-11 11:51
虚心向大前辈们请教:EROM_W(1,5,num1)里,后面的num1是什么作用?与:EROM_W(1,5)结果有啥不同?

终于明白了。因原码函数 void EROM_W(uchar n,uint x,uchar dat) 有3个参数,uchar n,为扇区,uint x,为地址,uchar dat ,是要写入的数据。EROM_W(1,5,num1),即为 第 1 扇区,第 5 字节,写入num1。悟了写出来,避免以后有我一样笨的能避坑。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表