找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6441|回复: 10
收起左侧

51单片机智能窗帘代码仿真资料分享

  [复制链接]
ID:199636 发表于 2020-3-9 10:20 | 显示全部楼层 |阅读模式
电路原理图如下:
智能窗帘原理图.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. /*************************************************************
  2.                       智能窗帘

  3. 补充说明:
  4. ***************************************************************/
  5. #include<reg52.h>                   //头文件
  6. #include<LCD1602.h>
  7. #include<DS1302.h>
  8. #include<28BYJ48.h>
  9. #include<EEPROM.h>
  10. #include<ADC0832.h>
  11. #include<HW.h>

  12. #define uchar unsigned char//宏定义
  13. #define uint unsigned int

  14. /*******************引脚定义*********************/
  15. sbit key_mode = P1^0;         //设置键
  16. sbit key_jia  = P1^1;         //加值键
  17. sbit key_jian = P1^2;         //减值键
  18. sbit key_ok   = P1^3;         //确定键

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  710.         //红外遥控切换设置下一个参数
  711.         if(hw_data=='>'&&set_f!=0)
  712.         {
  713.                 if(set_f==6)                                //日期、时间校准完
  714.                 {
  715.                         LCD_write_command(0x01);//清除屏幕显示
  716.                         delay_n40us(100);                //延时等待全部清除完毕
  717.                         set_f=13;                                //跳到校准窗帘状态
  718.                 }
  719.                 else
  720.                         if(set_f==10||set_f==12)
  721.                         {
  722.                                 LCD_write_command(0x01);     //清除屏幕显示
  723.                                 delay_n40us(100);                     //延时等待全部清除完毕
  724.                                 set_f=1;                                         //进入校准时间
  725.                         }
  726.                          else
  727.                                 set_f++;                                         //设置变量+1
  728.                 if(set_f>12)
  729.                 {
  730.                         Writeds1302 (WRITE_PROTECT,0X00);//禁止DS1302写保护
  731.                         LCD_write_command(0x01);         //清除屏幕显示
  732.                         delay_n40us(100);                         //延时等待全部清除完毕
  733.                         switch(mode)//根据对应的模式,设置对应的参数
  734.                         {
  735.                                 case 0: set_f=1; break;                 //手动模式
  736.                                 case 1: set_f=7; break;                 //定时模式
  737.                                 case 2: set_f=11; break;         //光控模式
  738.                                 default: break;
  739.                         }
  740.                 }
  741.         }
  742.         hw_data=0xff;//清除红外接收的数据
  743. }
  744. /********************************************************
  745. 函数名称:void mian()
  746. 函数作用:主函数
  747. 参数说明:
  748. ********************************************************/
  749. void main()
  750. {
  751.         uchar lowtime;         //记录上次采集光强的时间
  752.         uchar nums;                 //循环计数变量

  753.         if(key_ok==0)
  754.         {
  755.                 delayms(100);
  756.                 if(key_ok==0)
  757.                 {
  758.                         EEPROM_delete(0x2200);                                  //擦除扇区
  759.                         EEPROM_write(0x2200,8); //写入【定时时间】数据保存
  760.                         EEPROM_write(0x2210,30);//写入【定时时间】数据保存存
  761.                         EEPROM_write(0x2220,16);//写入【定时时间】数据保存存
  762.                         EEPROM_write(0x2230,20);//写入【定时时间】数据保存存
  763.                         EEPROM_write(0x2240,80);//写入【光强上限值】数据保存
  764.                         EEPROM_write(0x2250,30);//写入【光强下限值】数据保存

  765.                         EEPROM_delete(0x2400);  //擦除扇区
  766.                         EEPROM_write(0x2400,0); //写入【模式】数据保存
  767.                 }
  768.         }

  769.         ds[0]=EEPROM_read(0x2200);                  //读取存储的【定时时间】数据
  770.         ds[1]=EEPROM_read(0x2210);                  //读取存储的【定时时间】数据
  771.         ds[2]=EEPROM_read(0x2220);                  //读取存储的【定时时间】数据
  772.         ds[3]=EEPROM_read(0x2230);                  //读取存储的【定时时间】数据
  773.         light_up=EEPROM_read(0x2240);          //读取存储的【光强上限值】数据
  774.         light_down=EEPROM_read(0x2250);   //读取存储的【光强下限值】数据
  775.         mode=EEPROM_read(0x2400);         //读取存储的【模式】数据

  776.         HW_init();                                                //红外接收初始化
  777.         LCD_init();                                    //LCD1602初始化
  778.         ADC0832_read(0);
  779.         ADC0832_read(0);
  780.         while(1)                                                //死循环
  781.         {               
  782.                 scan();                                //按键检测处理

  783.                 if(set_f==0)                        //正常显示
  784.                 {
  785.                         nums++;                                //循环次数+1
  786.                         if(nums==10)                        //每循环10次,读取一次日期、时间
  787.                         {
  788.                                 nums=0;                                //重置循环次数
  789.                                 Read_time();        //读取日期、时间
  790.                         }
  791.                         if(time[0]!=lowtime)        //时间过去一秒
  792.                         {
  793.                                 lowtime=time[0];        //重新记录时间
  794.                                 light=ADC0832_read(0);//读取AD值
  795.                                 light=light*100/255;//转换为光强
  796.                         }
  797.                         display();                                //更新显示数据
  798.                 }
  799.                 else
  800.                         if(set_f<7)                       //校准日期、时间       
  801.                         {       
  802.                                 Read_time();       //读取日期、时间       
  803.                                 display2();
  804.                         }
  805.                         else
  806.                                 if(set_f<11)       //设置定时
  807.                                         display3();
  808.                                 else
  809.                                         if(set_f<13)   //设置光强控制值
  810.                                                 display4();         
  811.         }
  812. }
复制代码

所有资料51hei提供下载:
51智能窗帘.7z (4.32 MB, 下载次数: 173)

评分

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

查看全部评分

回复

使用道具 举报

ID:711872 发表于 2020-3-20 17:49 | 显示全部楼层
厉害了,努力赚黑币
回复

使用道具 举报

ID:711872 发表于 2020-3-20 17:49 | 显示全部楼层
厉害了,做下试试
回复

使用道具 举报

ID:366000 发表于 2020-4-21 00:26 来自手机 | 显示全部楼层
楼主,可以把整个文件发我吗?包括文档
回复

使用道具 举报

ID:733618 发表于 2020-4-21 11:01 来自手机 | 显示全部楼层
我也是从初学者过来的,看到论坛上很多问题就像看到当初的自己,温故而知新,帮别人解决问题,自己也能提升,多谢管理员给了一个这么好的平台
回复

使用道具 举报

ID:734207 发表于 2020-4-21 11:38 来自手机 | 显示全部楼层
你这个电路图有点小问题
回复

使用道具 举报

ID:566857 发表于 2020-4-26 14:46 | 显示全部楼层
一天会 发表于 2020-4-21 11:38
你这个电路图有点小问题

没有问题吧?我仿真了一下是可以运行的呀
回复

使用道具 举报

ID:368810 发表于 2020-5-23 09:53 | 显示全部楼层
宋哈娜 发表于 2020-4-26 14:46
没有问题吧?我仿真了一下是可以运行的呀

我感觉光强光弱电机转向都是一样呢?不应该是实现正转反转的吗?还是因为电机转速太快了看起来是一个转向?
回复

使用道具 举报

ID:759215 发表于 2020-5-23 15:57 | 显示全部楼层
努力赚黑币,太难了
回复

使用道具 举报

ID:822999 发表于 2020-10-28 09:34 来自手机 | 显示全部楼层
楼主运行无法生成hex文件
回复

使用道具 举报

ID:440526 发表于 2020-12-19 16:47 | 显示全部楼层
一切完美,哈哈
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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