找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4671|回复: 0
收起左侧

51单片机智能窗帘控制系统源程序与Proteus仿真图

[复制链接]
ID:651755 发表于 2021-5-23 13:18 | 显示全部楼层 |阅读模式
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.gif
51hei.png 51hei.png

元件清单:
10UF电解电容    C2
47UF电解电容    C6
光敏电阻    R10
限位开关    K1, K2
微动开关    KEY1, KEY2, KEY3, KEY4, KEY5
步进电机    P1
DC-002电源插座    P2
LCD1602液晶    Q1
红外一体接头    Q5
10K色环电阻    R1, R4, R5, R6, R8, R9
10K电位器    R2
10k排阻    R3
双掷开关    SW1
2Pi插针    U2
STC89C52单片机    U3
ADC0832模数转换芯片    U4
ULN2003电机驱动芯片    U5
DS1302时钟芯片    U6
12MHZ晶振    Y1
32.768KHZ晶振    Y2

单片机源程序如下:
  1. #include<reg52.h>                   //头文件
  2. #include<LCD1602.h>
  3. #include<DS1302.h>
  4. #include<28BYJ48.h>
  5. #include<EEPROM.h>
  6. #include<ADC0832.h>
  7. #include<HW.h>

  8. #define uchar unsigned char//宏定义
  9. #define uint unsigned int

  10. /*******************引脚定义*********************/
  11. sbit key_mode = P1^0;         //设置键
  12. sbit key_jia  = P1^1;         //加值键
  13. sbit key_jian = P1^2;         //减值键
  14. sbit key_ok   = P1^3;         //确定键

  15. sbit sw1=P3^7;           //全开 限位开关
  16. sbit sw2=P3^6;           //全关 限位开关
  17. /*******************变量定义*********************/
  18. uchar light_up,light_down;//存储光强上、下限值
  19. uchar set_f=0;                //设置选择标记,=0非设置,=1设置年,=2设置月,=3设置日,=4设置时,=5设置分,=6设置秒
  20.                                         //              =7设置定时-时,=8设置定时-分,=9设置定时-开关,=10设置窗帘打开/关闭
  21.                                         //                                =11设置光强上限,=12设置光强下限,=13设置校准窗帘位置

  22. uchar num;                        //计数变量
  23. uchar ds[4];            //定时控制开时、分、控制关时、分

  24. uchar mode=0;                //模式标记。=0手动,=1定时,=2光控
  25. uchar light;        //存储光强

  26. uint moto_num=0;  //记录窗帘位置
  27. uchar moto_state=0;//窗帘状态,=0已经关闭,=1处于运转过程中,=2已经打开
  28. bit moto_f=0;           //标记当前控制状态,=0控制关,=1控制开
  29. uchar code display_mode[3][3]={"SD\0","DS\0","GK\0"};//显示模式
  30. /********************************************************
  31. 函数名称:void delayms(uint ms)
  32. 函数作用:毫秒延时函数
  33. 参数说明:
  34. ********************************************************/
  35. void delayms(uint ms)
  36. {
  37.         unsigned char i=100,j;
  38.         for(;ms;ms--)
  39.         {
  40.                 while(--i)
  41.                 {
  42.                         j=10;
  43.                         while(--j);
  44.                 }
  45.         }
  46. }

  47. /********************************************************
  48. 函数名称:void display(void)
  49. 函数作用:正常显示日期、时间、光强等函数
  50. 参数说明:
  51. ********************************************************/
  52. void display(void)
  53. {
  54.         uint t[3];        

  55.         //显示时间
  56.         LCD_disp_char(0,2,ASCII[time[2]/10]);//显示时【0:表示第1列,2:表示第2行,所有关于显示都一样】
  57.         LCD_disp_char(1,2,ASCII[time[2]%10]);
  58.         LCD_disp_char(2,2,':');
  59.         LCD_disp_char(3,2,ASCII[time[1]/10]);//显示分【3:表示第4列,2:表示第2行,所有关于显示都一样】
  60.         LCD_disp_char(4,2,ASCII[time[1]%10]);
  61.         LCD_disp_char(5,2,':');
  62.         LCD_disp_char(6,2,ASCII[time[0]/10]);//显示秒
  63.         LCD_disp_char(7,2,ASCII[time[0]%10]);

  64.         //显示日期
  65.         LCD_disp_char(0,1,ASCII[time[6]/10]);//显示年
  66.         LCD_disp_char(1,1,ASCII[time[6]%10]);
  67.         LCD_disp_char(2,1,'/');
  68.         LCD_disp_char(3,1,ASCII[time[4]/10]);//显示月
  69.         LCD_disp_char(4,1,ASCII[time[4]%10]);
  70.         LCD_disp_char(5,1,'/');
  71.         LCD_disp_char(6,1,ASCII[time[3]/10]);//显示日
  72.         LCD_disp_char(7,1,ASCII[time[3]%10]);

  73.         //显示模式
  74.         lcd1602_write_character(9,1,display_mode[mode]);
  75.        
  76.         //显示光强
  77.         if(light>99)
  78.                 LCD_disp_char(12,1,ASCII[light/100]);
  79.         else
  80.                 LCD_disp_char(12,1,' ');
  81.         LCD_disp_char(13,1,ASCII[light%100/10]);
  82.         LCD_disp_char(14,1,ASCII[light%10]);
  83.         LCD_disp_char(15,1,'%');

  84.         //光强控制
  85.         if(mode==2)//光控模式
  86.         {         
  87.                 if((light>=light_up||light<light_down))//判断实际光强是否【大于等于上限 或 小于下限值】、当前处于打开状态
  88.                 {       
  89.                         moto_f=0;         //标记当前控制窗帘关闭  
  90.                         moto_state=1;//标记窗帘处于运转过程中
  91.                 }
  92.                 else
  93.                         if((light<light_up&&light>=light_down))//判断实际光强是否【大于等于下限值 并且 小于上限】、当前处于关闭状态
  94.                         {
  95.                                 moto_f=1;         //标记当前控制窗帘打开  
  96.                                 moto_state=1;//标记窗帘处于运转过程中
  97.                         }
  98.         }
  99.         else
  100.                 if(mode==1)//定时模式
  101.                 {
  102.                         t[0]=time[2]*60+time[1];//当前时间
  103.                         t[1]=ds[0]*60+ds[1];        //窗帘开启时间点
  104.                         t[2]=ds[2]*60+ds[3];        //窗帘关闭时间点
  105.                        
  106.                         if(t[1]<t[2])                         //0时 --> t[1] --> t[2] --> 24时
  107.                         {
  108.                                 if(t[0]>=t[1]&&t[0]<=t[2])
  109.                                         moto_f=1;            //标记当前需要打开窗帘
  110.                                 else
  111.                                         moto_f=0;                //标记当前需要关闭窗帘
  112.                         }
  113.                         else                                        //0时 --> t[2] --> t[1] --> 24时
  114.                         {
  115.                                 if(t[0]>=t[1]||t[0]<=t[2])
  116.                                         moto_f=1;                //标记当前需要打开窗帘
  117.                                 else
  118.                                         moto_f=0;                //标记当前需要关闭窗帘
  119.                         }
  120.                         moto_state=1;          //标记窗帘处于运转过程中
  121.                 }
  122.         if(moto_f==0&&moto_state!=0&&sw2!=0)//控制关闭窗帘
  123.         {
  124.                 if(moto_num==0)                          //控制次数减到0时,表示窗户已经关闭完成
  125.                 {
  126.                         BYJ48=P2&0xf0;                  //关闭步进电机
  127.                         moto_state=0;                  //标记窗帘处于关闭状态
  128.                         lcd1602_write_character(10,2,"ZT:OFF");
  129.                 }
  130.                 else
  131.                 {
  132.                         motor_z();                                  //步进电机正转
  133.                         moto_num--;                                  //控制次数-1
  134.                         lcd1602_write_character(10,2,"-->OFF");
  135.                 }               
  136.         }
  137.         else                  
  138.                 if(moto_f==1&&moto_state!=2&&sw1!=0)//控制打开窗帘
  139.                 {
  140.                         if(moto_num>=192)          //控制次数加到128时,表示窗户已经打开完成
  141.                         {
  142.                                 BYJ48=P2&0xf0;                  //关闭步进电机
  143.                                 moto_state=2;          //标记窗帘处于打开状态
  144.                                 lcd1602_write_character(10,2,"ZT:ON ");
  145.                         }
  146.                         else
  147.                         {
  148.                                 motor_f();                          //步进电机反转
  149.                                 moto_num++;                          //控制次数+1
  150.                                 lcd1602_write_character(10,2,"-->ON ");
  151.                         }               
  152.                 }
  153.                 else                                          //窗户处于停止状态
  154.                 {
  155.                         BYJ48=P2&0xf0;                  //关闭步进电机
  156.                         if(moto_state==0||sw2==0)
  157.                                 lcd1602_write_character(10,2,"ZT:OFF");
  158.                         else
  159.                                 if(moto_state==2||sw1==0)
  160.                                         lcd1602_write_character(10,2,"ZT:ON ");       
  161.                 }         
  162. }
  163. /********************************************************
  164. 函数名称:void display2(void)
  165. 函数作用:显示调整日期、时间函数
  166. 参数说明:
  167. ********************************************************/
  168. void display2()
  169. {
  170.         num++;

  171.         lcd1602_write_character(1,1,"Date:");
  172.         lcd1602_write_character(1,2,"Time:");
  173.        
  174.         if(num%2==0)        //偶数次显示,奇数次不显示。这样就会有闪烁效果,可以清楚看到当前设置的是哪个值
  175.         {
  176.                 LCD_disp_char(6,1,ASCII[time[6]/10]); //显示年
  177.                 LCD_disp_char(7,1,ASCII[time[6]%10]);
  178.                 LCD_disp_char(8,1,'/');  
  179.                 LCD_disp_char(9,1,ASCII[time[4]/10]); //显示月
  180.                 LCD_disp_char(10,1,ASCII[time[4]%10]);          
  181.                 LCD_disp_char(11,1,'/');
  182.                 LCD_disp_char(12,1,ASCII[time[3]/10]);//显示日
  183.                 LCD_disp_char(13,1,ASCII[time[3]%10]);
  184.        
  185.                 LCD_disp_char(6,2,ASCII[time[2]/10]); //显示时
  186.                 LCD_disp_char(7,2,ASCII[time[2]%10]);
  187.                 LCD_disp_char(8,2,':');  
  188.                 LCD_disp_char(9,2,ASCII[time[1]/10]); //显示分
  189.                 LCD_disp_char(10,2,ASCII[time[1]%10]);          
  190.                 LCD_disp_char(11,2,':');
  191.                 LCD_disp_char(12,2,ASCII[time[0]/10]);//显示秒
  192.                 LCD_disp_char(13,2,ASCII[time[0]%10]);
  193.         }       
  194.         else                        //奇数次不显示
  195.         {
  196.                 switch(set_f)//根据当前设置的内容,对应位置闪烁
  197.                 {
  198.                         case 1: lcd1602_write_character(6,1,"  "); break;
  199.                         case 2: lcd1602_write_character(9,1,"  "); break;
  200.                         case 3: lcd1602_write_character(12,1,"  "); break;
  201.                         case 4: lcd1602_write_character(6,2,"  "); break;
  202.                         case 5: lcd1602_write_character(9,2,"  "); break;
  203.                         case 6: lcd1602_write_character(12,2,"  "); break;
  204.                         default: break;
  205.                 }
  206.         }       
  207. }
  208. /********************************************************
  209. 函数名称:void display3(void)
  210. 函数作用:显示调整定时时间函数
  211. 参数说明:
  212. ********************************************************/
  213. void display3()
  214. {
  215.         num++;
  216.         lcd1602_write_character(0, 1, "Sets timer time:");
  217.         lcd1602_write_character(7, 2, "--");
  218.         if(num%2==0)        //偶数次显示,奇数次不显示。这样就会有闪烁效果,可以清楚看到当前设置的是哪个值
  219.         {            
  220.                 LCD_disp_char(1, 2, ASCII[ds[0]/10]);  //显示定时开-时
  221.                 LCD_disp_char(2, 2, ASCII[ds[0]%10]);   
  222.                 LCD_disp_char(3, 2, ':');
  223.                 LCD_disp_char(4, 2, ASCII[ds[1]/10]);  //显示定时开-分
  224.                 LCD_disp_char(5, 2, ASCII[ds[1]%10]);

  225.                 LCD_disp_char(10, 2, ASCII[ds[2]/10]); //显示定时关-时
  226.                 LCD_disp_char(11, 2, ASCII[ds[2]%10]);   
  227.                 LCD_disp_char(12, 2, ':');
  228.                 LCD_disp_char(13, 2, ASCII[ds[3]/10]); //显示定时关-分
  229.                 LCD_disp_char(14, 2, ASCII[ds[3]%10]);
  230.         }
  231.         else                         //奇数次不显示
  232.         {
  233.                 switch(set_f)//根据当前设置的内容,对应位置闪烁
  234.                 {
  235.                         case 7: lcd1602_write_character(1,2,"  "); break;
  236.                         case 8: lcd1602_write_character(4,2,"  "); break;
  237.                         case 9: lcd1602_write_character(10,2,"  "); break;
  238.                         case 10: lcd1602_write_character(13,2,"  "); break;
  239.                         default: break;
  240.                 }
  241.         }
  242. }
  243. /********************************************************
  244. 函数名称:void display4(void)
  245. 函数作用:显示调整光强控制函数
  246. 参数说明:
  247. ********************************************************/
  248. void display4(void)
  249. {
  250.         num++;

  251.         lcd1602_write_character(0, 1, "Light_Up  :");
  252.         lcd1602_write_character(0, 2, "Light_Down:");
  253.         LCD_disp_char(15,1,'%');
  254.         LCD_disp_char(15,2,'%');
  255.         if(num%2==0)        //偶数次显示,奇数次不显示。这样就会有闪烁效果,可以清楚看到当前设置的是哪个值
  256.         {
  257.                 LCD_disp_char(12, 1, ASCII[light_up/100]);           //显示光强上限值
  258.                 LCD_disp_char(13, 1, ASCII[light_up%100/10]);
  259.                 LCD_disp_char(14, 1, ASCII[light_up%10]);   
  260.        
  261.                 LCD_disp_char(12, 2, ASCII[light_down/100]);   //显示光强下限值
  262.                 LCD_disp_char(13, 2, ASCII[light_down%100/10]);       
  263.                 LCD_disp_char(14, 2, ASCII[light_down%10]);
  264.         }
  265.         else                           //奇数次不显示
  266.         {
  267.                 switch(set_f)//根据当前设置的内容,对应位置闪烁
  268.                 {
  269.                         case 11: lcd1602_write_character(12,1,"   "); break;
  270.                         case 12: lcd1602_write_character(12,2,"   "); break;
  271.                         default: break;
  272.                 }
  273.         }
  274. }
  275. /********************************************************
  276. 函数名称:void scan(void)
  277. 函数作用:按键查询处理函数
  278. 参数说明:
  279. ********************************************************/
  280. void scan(void)
  281. {
  282.         //设置键
  283.         if(hw_data=='B'||key_mode==0)      //按键按下
  284.         {  
  285.                 delayms(7);                                            //延时消抖
  286.                 if(hw_data=='B'||key_mode==0)  //再次确认按键按下       
  287.                 {
  288.                         BYJ48=P2&0xf0;                            //关闭步进电机
  289.                         if(set_f==6)                                //日期、时间校准完
  290.                         {
  291.                                 LCD_write_command(0x01);//清除屏幕显示
  292.                                 delay_n40us(100);                //延时等待全部清除完毕
  293.                                 set_f=13;                                //跳到校准窗帘状态
  294.                         }
  295.                         else
  296.                                 if(set_f==0)            //进入设置先清除屏幕,显示设置部分
  297.                                 {
  298.                                         Writeds1302 (WRITE_PROTECT,0X00);//禁止DS1302写保护
  299.                                         LCD_write_command(0x01);         //清除屏幕显示
  300.                                         delay_n40us(100);                         //延时等待全部清除完毕
  301.                                         switch(mode)//根据对应的模式,设置对应的参数
  302.                                         {
  303.                                                 case 0: set_f=1; break;                 //手动模式
  304.                                                 case 1: set_f=7; break;                 //定时模式
  305.                                                 case 2: set_f=11; break;         //光控模式
  306.                                                 default: break;
  307.                                         }       
  308.                                 }
  309.                                 else
  310.                                         if(set_f==10||set_f==12)//进入设置日期时间
  311.                                         {
  312.                                                 LCD_write_command(0x01);     //清除屏幕显示
  313.                                                 delay_n40us(100);                     //延时等待全部清除完毕
  314.                                                 set_f=1;                                         //进入校准时间
  315.                                         }
  316.                                          else
  317.                                                 set_f++;                                         //设置变量+1
  318.                         if(set_f>12)
  319.                         {
  320.                                 set_f=0;                                                         //重置设置变量

  321.                                 Writeds1302 (WRITE_MINUTE,(time[1]/10)*16+time[1]%10);//将设置好的时间写入DS1302
  322.                                 Writeds1302 (WRITE_SECOND,(time[0]/10)*16+time[0]%10);

  323.                                 EEPROM_delete(0x2200);                                  //擦除扇区
  324.                                 EEPROM_write(0x2200,ds[0]);     //写入【定时时间】数据保存
  325.                                 EEPROM_write(0x2210,ds[1]);     //写入【定时时间】数据保存存
  326.                                 EEPROM_write(0x2220,ds[2]);     //写入【定时时间】数据保存存
  327.                                 EEPROM_write(0x2230,ds[3]);     //写入【定时时间】数据保存存
  328.                                 EEPROM_write(0x2240,light_up);  //写入【光强上限值】数据保存
  329.                                 EEPROM_write(0x2250,light_down);//写入【光强下限值】数据保存

  330.                                 LCD_write_command(0x01);             //清除屏幕显示
  331.                                 delay_n40us(100);                             //延时等待全部清除完毕
  332.                         }                        
  333.                 }
  334.                 while(!key_mode);                            //等待按键松开       
  335.         }
  336.         //确定
  337.         if(hw_data=='Q'||key_ok==0)                                //按键按下
  338.         {
  339.                 delayms(7);                                                                //延时消抖
  340.                 if((hw_data=='Q'||key_ok==0)&&set_f!=0)//再次确认按键按下
  341.                 {
  342.                         if(set_f<7)
  343.                         {
  344.                                 Writeds1302 (WRITE_MINUTE,(time[1]/10)*16+time[1]%10);//将设置好的时间写入DS1302
  345.                                 Writeds1302 (WRITE_SECOND,(time[0]/10)*16+time[0]%10);
  346.                         }
  347.                         set_f=0;                                                        //重置设置变量
  348.        
  349.                         EEPROM_delete(0x2200);                                  //擦除扇区
  350.                         EEPROM_write(0x2200,ds[0]);     //写入【定时时间】数据保存
  351.                         EEPROM_write(0x2210,ds[1]);     //写入【定时时间】数据保存存
  352.                         EEPROM_write(0x2220,ds[2]);     //写入【定时时间】数据保存存
  353.                         EEPROM_write(0x2230,ds[3]);     //写入【定时时间】数据保存存
  354.                         EEPROM_write(0x2240,light_up);  //写入【光强上限值】数据保存
  355.                         EEPROM_write(0x2250,light_down);//写入【光强下限值】数据保存

  356.                         LCD_write_command(0x01);            //清除屏幕显示
  357.                         delay_n40us(100);                            //延时等待全部清除完毕
  358.                 }
  359.                 else
  360.                         if(key_ok==0&&set_f==0)                            //切换模式
  361.                         {
  362.                                 mode++;                                                        //模式变量+1
  363.                                 if(mode>=3)                                                //最大3个模式
  364.                                         mode=0;                                                //重新回到第1个模式
  365.                                 if(moto_state==1)                                //如果处于运转过程中
  366.                                 {
  367.                                         if(moto_f==0)                                //控制步进电机关闭
  368.                                                 moto_state=0;
  369.                                         else                                                //控制步进电机打开
  370.                                                 moto_state=2;               
  371.                                 }
  372.                                 EEPROM_delete(0x2400);                    //擦除扇区
  373.                                 EEPROM_write(0x2400,mode);      //写入【模式】数据保存               
  374.                         }
  375.                 while(!key_ok);                                //等待按键松开
  376.         }
  377.         //加键        ,下面减键内容一样       
  378.         if(hw_data=='+'||key_jia==0)
  379.         {
  380.                 delayms(7);
  381.                 if((hw_data=='+'||key_jia==0)&&set_f!=0)
  382.                 {
  383.                         if(set_f==1)           //设置年
  384.                         {
  385.                                 time[6]++;                                                        //年份+1
  386.                                 time[6]=(time[6]/10)*16+time[6]%10;        //将年份转换成16进制,例如:16年-->0x16
  387.                                 if(time[6]>0x79)                                        //判断是否达到最大年份79年
  388.                                         time[6]=0x00;                                        //重新回到00年
  389.                                 Writeds1302 (WRITE_YEA,time[6]);        //将设置好的年份写入到DS1302存储起来
  390.                         }
  391.                
  392.                         if(set_f==2)           //设置月
  393.                         {
  394.                                 time[4]++;                                                        //月份+1
  395.                                 time[4]=(time[4]/10)*16+time[4]%10;        //将月份转换成16进制,例如:08月-->0x08
  396.                                 if(time[4]>0x12)                                        //判断是否达到最大月份12月
  397.                                         time[4]=0x01;                                        //重新回到01月
  398.                                 Writeds1302 (WRITE_MONTH,time[4]);        //将设置好的月份写入到DS1302存储起来
  399.                         }
  400.                
  401.                         if(set_f==3)         //设置日
  402.                         {
  403.                                 time[3]++;                                                        //日份+1
  404.                                 time[3]=(time[3]/10)*16+time[3]%10;        //将日份转换成16进制,例如:15日-->0x15
  405.                                 if(time[4]==1||time[4]==3||time[4]==5||time[4]==7||time[4]==8||time[4]==10||time[4]==12)//1,3,5,7,8,10,12为大月,每月31天
  406.                                 {
  407.                                         if(time[3]>0x31)                                //判断是否达到最大日份31日
  408.                                                 time[3]=0x01;                                //重新回到01日
  409.                                 }
  410.                                 else                                                                //否者2,4,6,9,11为小月
  411.                                 {
  412.                                         if(time[4]==0x02)                                //如果是2月,需要区分闰、平年
  413.                                         {
  414.                                                 if(((!(time[6]%4) && (time[6]%100)) || !(time[6]%400))==0)//如果闰年
  415.                                                 {
  416.                                                         if(time[3]>0x28)                //判断是否达到最大日份28日
  417.                                                                 time[3]=0x01;                //重新回到01日
  418.                                                 }
  419.                                                 else                                                //否者平年
  420.                                                 {
  421.                                                         if(time[3]>0x29)                //判断是否达到最大日份29日
  422.                                                                 time[3]=0x01;                //重新回到01日
  423.                                                 }
  424.                                         }
  425.                                         else                                                        //否者为剩下的月份
  426.                                         {
  427.                                                 if(time[3]>0x30)                        //判断是否达到最大日份30日
  428.                                                         time[3]=0x01;                        //重新回到01日
  429.                                         }
  430.                                 }       
  431.                                 Writeds1302 (WRITE_DAY,time[3]);        //将设置好的日份写入到DS1302存储起来
  432.                         }
  433.                
  434.                         if(set_f==4)          //设置时,同上
  435.                         {                       
  436.                                 time[2]++;
  437.                                 time[2]=(time[2]/10)*16+time[2]%10;
  438.                                 if(time[2]>0x23)
  439.                                         time[2]=0x00;
  440.                                 Writeds1302 (WRITE_HOUR,time[2]);       
  441.                         }
  442.                
  443.                         if(set_f==5)          //设置分,同上
  444.                         {
  445.                                 time[1]++;
  446.                                 time[1]=(time[1]/10)*16+time[1]%10;
  447.                                 if(time[1]>0x59)
  448.                                         time[1]=0x00;
  449.                                 Writeds1302 (WRITE_MINUTE,time[1]);       
  450.                         }
  451.                
  452.                         if(set_f==6)         //设置秒,同上
  453.                         {
  454.                                 time[0]++;
  455.                                 time[0]=(time[0]/10)*16+time[0]%10;
  456.                                 if(time[0]>0x59)
  457.                                         time[0]=0x00;
  458.                                 Writeds1302 (WRITE_SECOND,time[0]);       
  459.                         }
  460.                        
  461.                         if(set_f==7)     //设置定时起始时间——时      
  462.                         {
  463.                                 if(ds[0]<23)
  464.                                         ds[0]++;  
  465.                                 else
  466.                                         ds[0]=0;                       
  467.                         }
  468.        
  469.                         if(set_f==8)    //设置定时起始时间——分        
  470.                         {
  471.                                 if(ds[1]<59)
  472.                                         ds[1]++;  
  473.                                 else
  474.                                         ds[1]=0;                 
  475.                         }

  476.                         if(set_f==9)     //设置定时结束时间——时      
  477.                         {
  478.                                 if(ds[2]<23)
  479.                                         ds[2]++;  
  480.                                 else
  481.                                         ds[2]=0;                       
  482.                         }
  483.        
  484.                         if(set_f==10)    //设置定时结束时间——分        
  485.                         {
  486.                                 if(ds[3]<59)
  487.                                         ds[3]++;  
  488.                                 else
  489.                                         ds[3]=0;                 
  490.                         }
  491.                         if(set_f==11)    //设置 光强上限值
  492.                         {
  493.                                 if(light_up<99)//最大值可设置99%
  494.                                         light_up++;//光强上限值+1%
  495.                         }
  496.        
  497.                         if(set_f==12)    //设置 光强下限值
  498.                         {
  499.                                 if(light_down<99&&light_down+1<light_up)//最大值可设置99%,并且下限不能超过上限
  500.                                         light_down++;//光强下限值+1%
  501.                         }
  502.                 }
  503.                 else
  504.                         if((hw_data=='+'||key_jia==0)&&set_f==0&&mode==0)//手动控制窗帘打开
  505.                         {         
  506.                                 if(moto_state==1&&moto_f==1)//已经在控制状态。并且控制打开
  507.                                         moto_state=2;    //停止运作
  508.                                 else
  509.                                 {
  510.                                         if(moto_num<192)//判断是否不处于打开状态
  511.                                         {
  512.                                                 moto_f=1;         //控制开闭窗
  513.                                                 moto_state=1;    //开启运作
  514.                                         }
  515.                                 }
  516.                                 while(!key_jia);     //等待按键松开
  517.                         }       
  518.         }
  519.         //减键
  520.         if(hw_data=='-'||key_jian==0)
  521.         {
  522.                 delayms(7);
  523.                 if((hw_data=='-'||key_jian==0)&&set_f!=0)
  524.                 {
  525.                         if(set_f==1)         //设置年
  526.                         {
  527.                                 if(time[6]==0)                                           //判断当前是否为00年
  528.                                         time[6]=79;                                           //如果是回到最大年份:79年
  529.                                 else
  530.                                         time[6]--;                                           //否者,年份-1
  531.                                 time[6]=(time[6]/10)*16+time[6]%10;//将年份转换成16进制,例如:16年-->0x16                       
  532.                                 Writeds1302 (WRITE_YEA,time[6]);   //将设置好的年份写入到DS1302存储起来
  533.                         }
  534.        
  535.                         if(set_f==2)         //设置月,同上
  536.                         {
  537.                                 if(time[4]==1)
  538.                                         time[4]=12;
  539.                                 else
  540.                                         time[4]--;
  541.                                 time[4]=(time[4]/10)*16+time[4]%10;
  542.                                 Writeds1302 (WRITE_MONTH,time[4]);               
  543.                         }
  544.        
  545.                         if(set_f==3)        //设置日,同上
  546.                         {
  547.                                 time[3]--;
  548.                                 time[3]=(time[3]/10)*16+time[3]%10;
  549.                                 if(time[4]==1||time[4]==3||time[4]==5||time[4]==7||time[4]==8||time[4]==10||time[4]==12)
  550.                                 {
  551.                                         if(time[3]<0x01)
  552.                                                 time[3]=0x31;
  553.                                 }
  554.                                 else
  555.                                 {
  556.                                         if(time[4]==0x02)
  557.                                         {
  558.                                                 if(((!(time[6]%4) && (time[6]%100)) || !(time[6]%400))==0)
  559.                                                 {
  560.                                                         if(time[3]<0x01)
  561.                                                                 time[3]=0x28;
  562.                                                 }
  563.                                                 else
  564.                                                 {
  565.                                                         if(time[3]<0x01)
  566.                                                                 time[3]=0x29;
  567.                                                 }
  568.                                         }
  569.                                         else
  570.                                         {
  571.                                                 if(time[3]<0x01)
  572.                                                         time[3]=0x30;
  573.                                         }
  574.                                 }       
  575.                                 Writeds1302 (WRITE_DAY,time[3]);               
  576.                         }
  577.        
  578.                         if(set_f==4)        //设置时,同上
  579.                         {                       
  580.                                 if(time[2]==0)
  581.                                         time[2]=23;
  582.                                 else
  583.                                         time[2]--;
  584.                                 time[2]=(time[2]/10)*16+time[2]%10;
  585.                                 Writeds1302 (WRITE_HOUR,time[2]);               
  586.                         }
  587.        
  588.                         if(set_f==5)        //设置分,同上
  589.                         {
  590.                                 if(time[1]==0)
  591.                                         time[1]=59;
  592.                                 else
  593.                                         time[1]--;
  594.                                 time[1]=(time[1]/10)*16+time[1]%10;
  595.                                 Writeds1302 (WRITE_MINUTE,time[1]);               
  596.                         }
  597.        
  598.                         if(set_f==6)        //设置秒,同上
  599.                         {
  600.                                 if(time[0]==0)
  601.                                         time[0]=59;
  602.                                 else
  603.                                         time[0]--;
  604.                                 time[0]=(time[0]/10)*16+time[0]%10;
  605.                                 Writeds1302 (WRITE_SECOND,time[0]);                       
  606.                         }
  607.                         if(set_f==7)     //设置定时起始时间——时      
  608.                         {
  609.                                 if(ds[0]>0)
  610.                                         ds[0]--;  
  611.                                 else
  612.                                         ds[0]=23;                       
  613.                         }
  614.        
  615.                         if(set_f==8)    //设置定时起始时间——分        
  616.                         {
  617.                                 if(ds[1]>0)
  618.                                         ds[1]--;  
  619.                                 else
  620.                                         ds[1]=59;                 
  621.                         }

  622.                         if(set_f==9)     //设置定时结束时间——时      
  623.                         {
  624.                                 if(ds[2]>0)
  625.                                         ds[2]--;  
  626.                                 else
  627.                                         ds[2]=23;                       
  628.                         }
  629.        
  630.                         if(set_f==10)    //设置定时结束时间——分        
  631.                         {
  632.                                 if(ds[3]>0)
  633.                                         ds[3]--;  
  634.                                 else
  635.                                         ds[3]=59;                 
  636.                         }

  637.                         if(set_f==11)    //设置 光强上限值
  638.                         {
  639.                                 if(light_up!=0&&light_up>light_down+1)//最小值可设置成0,并且上限值要大于下限值
  640.                                         light_up--;  //光强上限值-1%
  641.                         }
  642.        
  643.                         if(set_f==12)    //设置 光强下限值
  644.                         {
  645.                                 if(light_down!=0)//最小值可设置成0
  646.                                         light_down--;//光强下限值-1%
  647.                         }
  648.                 }
  649.                 else
  650.                         if((hw_data=='-'||key_jian==0)&&set_f==0&&mode==0)//手动控制窗户关闭
  651.                         {
  652.                                 if(moto_state==1&&moto_f==0)//已经在控制状态。并且控制打开
  653.                                         moto_state=0;    //停止运作
  654.                                 else
  655.                                 {
  656.                                         if(moto_num>0)//判断是否不处于打开状态
  657.                                         {
  658.                                                 moto_f=0;         //控制开闭窗
  659.                                                 moto_state=1;    //开启运作
  660.                                         }
  661.                                 }
  662.                                 while(!key_jian);    //等待按键松开       
  663.                         }
  664.         }
  665.         //红外遥控切换模式
  666.         if(hw_data=='|'&&set_f==0)
  667.         {
  668.                 mode++;                                                        //模式变量+1
  669.                 if(mode>=3)                                                //最大3个模式
  670.                         mode=0;                                                //重新回到第1个模式
  671.                 if(moto_state==1)                                //如果处于运转过程中
  672.                 {
  673.                         if(moto_f==0)                                //控制步进电机关闭
  674.                                 moto_state=0;
  675.                         else                                                //控制步进电机打开
  676.                                 moto_state=2;               
  677.                 }
  678.                 EEPROM_delete(0x2400);                    //擦除扇区
  679.                 EEPROM_write(0x2400,mode);      //写入【模式】数据保存
  680.         }

  681.         //红外遥控切换设置上一个参数
  682.         if(hw_data=='<'&&set_f!=0)
  683.         {
  684.                 if(set_f==7||set_f==11)
  685.                 {
  686.                         LCD_write_command(0x01);    //清除屏幕显示
  687.                         delay_n40us(100);                    //延时等待全部清除完毕
  688.                         set_f=6;
  689.                 }
  690.                 else
  691.                         if(set_f==1)
  692.                         {
  693.                                 LCD_write_command(0x01);//清除屏幕显示
  694.                                 delay_n40us(100);                //延时等待全部清除完毕
  695.                                 switch(mode)//根据对应的模式,设置对应的参数
  696.                                 {
  697.                                         case 0: set_f=6; break;        //手动模式
  698.                                         case 1: set_f=10; break;//定时模式
  699.                                         case 2: set_f=12; break;//光控模式
  700.                                         default: break;
  701.                                 }
  702.                         }
  703.                         else
  704.                                 set_f--;
  705.         }

  706.         //红外遥控切换设置下一个参数
  707.         if(hw_data=='>'&&set_f!=0)
  708.         {
  709.                 if(set_f==6)                                //日期、时间校准完
  710.                 {
  711.                         LCD_write_command(0x01);//清除屏幕显示
  712.                         delay_n40us(100);                //延时等待全部清除完毕
  713.                         set_f=13;                                //跳到校准窗帘状态
  714.                 }
  715.                 else
  716.                         if(set_f==10||set_f==12)
  717.                         {
  718.                                 LCD_write_command(0x01);     //清除屏幕显示
  719.                                 delay_n40us(100);                     //延时等待全部清除完毕
  720.                                 set_f=1;                                         //进入校准时间
  721.                         }
  722.                          else
  723.                                 set_f++;                                         //设置变量+1
  724.                 if(set_f>12)
  725.                 {
  726.                         Writeds1302 (WRITE_PROTECT,0X00);//禁止DS1302写保护
  727.                         LCD_write_command(0x01);         //清除屏幕显示
  728. ……………………

  729. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
基于单片机的智能窗帘.7z (8.65 MB, 下载次数: 181)

评分

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

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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