找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 751|回复: 4
收起左侧

基于51单片机的智能窗帘有三个模式 程序及Proteus仿真图

[复制链接]
ID:1122159 发表于 2024-6-7 22:24 | 显示全部楼层 |阅读模式
第一个模式为手动控制加语音控制
第二个模式可以设置定时
第三个模式设置光照阈值来自动控制窗帘

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)

手动模式加语音

手动模式加语音

手动模式加语音


定时模式

定时模式

定时模式


3.png

运动

运动

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>

  3. #define uchar unsigned char                // 以后unsigned char就可以用uchar代替
  4. #define uint  unsigned int                // 以后unsigned int 就可以用uint 代替


  5. sbit ADC_CS     = P1^6;                         // ADC0832的CS引脚
  6. sbit ADC_CLK    = P1^7;                         // ADC0832的CLK引脚
  7. sbit ADC_DAT    = P3^2;                         // ADC0832的DI/DO引脚
  8. sbit SCK_P      = P1^0;                                // 时钟芯片DS1302的SCK管脚
  9. sbit SDA_P      = P1^1;                                // 时钟芯片DS1302的SDA管脚
  10. sbit RST_P      = P1^2;                                // 时钟芯片DS1302的RST管脚
  11. sbit LcdRs_P    = P1^3;       // 1602液晶的RS管脚      
  12. sbit LcdRw_P    = P1^4;       // 1602液晶的RW管脚
  13. sbit LcdEn_P    = P1^5;       // 1602液晶的EN管脚
  14. sbit KeyMode_P  = P3^3;                                // 模式切换
  15. sbit KeySet_P   = P3^4;                                // 设置时间按键
  16. sbit KeySet2_P  = P3^5;                                // 设置时间模式的开关时间和光照控制强度
  17. sbit KeyDown_P  = P3^6;                                // 减按键
  18. sbit KeyUp_P    = P3^7;                                // 加按键
  19. sbit Led_P      = P2^0;                                // 指示灯
  20. sbit YYOPEN                        =        P3^0;



  21. uchar gMode=1;                                                                // 1是手动模式,2是时间自动模式,3是亮度自动模式
  22. uchar OpenHour    = 18;                                // 开启窗帘的小时
  23. uchar OpenMinute  = 20;                                // 开启窗帘的分钟
  24. uchar CloseHour   = 10;                                // 关闭窗帘的小时
  25. uchar CloseMinute = 30;                                // 关闭窗帘的分钟
  26. uchar gLight      = 40;                                // 窗帘开关的阈值
  27. uchar gLightmax=80;
  28. uchar code Clock[]={0x80,0x40,0x20,0x10};                         // 步进电机顺时针旋转数组
  29. uchar code AntiClock[]={0x10,0x20,0x40,0x80};                // 步进电机逆时针旋转数组

  30. uchar TimeBuff[7]={17,9,1,6,18,30,40};                                        // 时间数组,默认2017年9月1日,星期五,18:30:40
  31. // TimeBuff[0] 代表年份,范围00-99
  32. // TimeBuff[1] 代表月份,范围1-12
  33. // TimeBuff[2] 代表日期,范围1-31
  34. // TimeBuff[3] 代表星期,范围1-7
  35. // TimeBuff[4] 代表小时,范围00-23
  36. // TimeBuff[5] 代表分钟,范围00-59
  37. // TimeBuff[6] 代表秒钟,范围00-59



  38. /*********************************************************/
  39. // 毫秒级的延时函数,time是要延时的毫秒数
  40. /*********************************************************/
  41. void DelayMs(uint time)
  42. {
  43.         uint i,j;
  44.         for(i=0;i<time;i++)
  45.                 for(j=0;j<112;j++);
  46. }


  47. /*********************************************************/
  48. // 1602液晶写命令函数,cmd就是要写入的命令
  49. /*********************************************************/
  50. void LcdWriteCmd(uchar cmd)
  51. {
  52.         LcdRs_P = 0;
  53.         LcdRw_P = 0;
  54.         LcdEn_P = 0;
  55.         P0=cmd;
  56.         DelayMs(2);
  57.         LcdEn_P = 1;   
  58.         DelayMs(2);
  59.         LcdEn_P = 0;        
  60. }


  61. /*********************************************************/
  62. // 1602液晶写数据函数,dat就是要写入的数据
  63. /*********************************************************/
  64. void LcdWriteData(uchar dat)
  65. {
  66.         LcdRs_P = 1;
  67.         LcdRw_P = 0;
  68.         LcdEn_P = 0;
  69.         P0=dat;
  70.         DelayMs(2);
  71.         LcdEn_P = 1;   
  72.         DelayMs(2);
  73.         LcdEn_P = 0;
  74. }


  75. /*********************************************************/
  76. // 1602液晶初始化函数
  77. /*********************************************************/
  78. void LcdInit()
  79. {
  80.         LcdWriteCmd(0x38);        // 16*2显示,5*7点阵,8位数据口
  81.         LcdWriteCmd(0x0C);        // 开显示,不显示光标
  82.         LcdWriteCmd(0x06);        // 地址加1,当写入数据后光标右移
  83.         LcdWriteCmd(0x01);        // 清屏
  84. }


  85. /*********************************************************/
  86. // 液晶光标定位函数
  87. /*********************************************************/
  88. void LcdGotoXY(uchar line,uchar column)
  89. {
  90.         // 第一行
  91.         if(line==0)        
  92.                 LcdWriteCmd(0x80+column);
  93.         // 第二行
  94.         if(line==1)        
  95.                 LcdWriteCmd(0x80+0x40+column);
  96. }


  97. /*********************************************************/
  98. // 液晶输出字符串函数
  99. /*********************************************************/
  100. void LcdPrintStr(uchar *str)
  101. {
  102.         while(*str!='\0')
  103.                         LcdWriteData(*str++);
  104. }


  105. /*********************************************************/
  106. // 液晶输出数字(0-99)
  107. /*********************************************************/
  108. void LcdPrintNum(uchar num)
  109. {
  110.         LcdWriteData(num/10+48);                // 十位
  111.         LcdWriteData(num%10+48);                 // 个位
  112. }


  113. /*********************************************************/
  114. // 显示模式
  115. /*********************************************************/
  116. void LcdPrintMode(uchar num)
  117. {
  118.         switch(num)                        
  119.         {
  120.                 case 1: LcdPrintStr("Manual");        break;
  121.                 case 2: LcdPrintStr("Timing");        break;
  122.                 case 3: LcdPrintStr("Liging");        break;
  123.                 default:                                                                                                break;
  124.         }
  125. }


  126. /*********************************************************/
  127. // 液晶显示内容的初始化
  128. /*********************************************************/
  129. void LcdShowInit()
  130. {
  131.         LcdGotoXY(0,0);
  132.         LcdPrintStr("20  -  -     :  ");
  133.         LcdGotoXY(1,0);
  134.         LcdPrintStr("           gz:  ");
  135.         LcdGotoXY(1,0);
  136.         LcdPrintMode(gMode);
  137. }



  138. /*********************************************************/
  139. // 刷新时间显示
  140. /*********************************************************/
  141. void FlashTime()
  142. {
  143.         LcdGotoXY(0,2);                                                                                // 年份
  144.         LcdPrintNum(TimeBuff[0]);
  145.         LcdGotoXY(0,5);                                                                                // 月份
  146.         LcdPrintNum(TimeBuff[1]);
  147.         LcdGotoXY(0,8);                                                                                // 日期
  148.         LcdPrintNum(TimeBuff[2]);
  149.         LcdGotoXY(0,11);                                                                        // 小时
  150.         LcdPrintNum(TimeBuff[4]);
  151.         LcdGotoXY(0,14);                                                                        // 分钟
  152.         LcdPrintNum(TimeBuff[5]);
  153.         LcdGotoXY(0,13);                                                                        // 秒钟
  154.         if(TimeBuff[6]%2==0)                                                        // 秒钟是偶数显示冒号
  155.                 LcdWriteData(':');
  156.         else                                                                                                                        // 秒钟是奇数显示空格
  157.                 LcdWriteData(' ');
  158. }


  159. /*********************************************************/
  160. // 初始化DS1302
  161. /*********************************************************/
  162. void DS1302_Init(void)
  163. {
  164.         RST_P=0;                        // RST脚置低
  165.         SCK_P=0;                        // SCK脚置低
  166.         SDA_P=0;                        // SDA脚置低                                
  167. }


  168. /*********************************************************/
  169. // 从DS1302读出一字节数据
  170. /*********************************************************/
  171. uchar DS1302_Read_Byte(uchar addr)
  172. {
  173.         uchar i;
  174.         uchar temp;
  175.         
  176.         RST_P=1;                                                               
  177.         
  178.         /* 写入目标地址:addr*/
  179.         for(i=0;i<8;i++)
  180.         {     
  181.                 if(addr&0x01)
  182.                         SDA_P=1;
  183.                 else
  184.                         SDA_P=0;
  185.                
  186.                 SCK_P=1;
  187.                 _nop_();
  188.                 SCK_P=0;
  189.                 _nop_();
  190.                
  191.                 addr=addr>> 1;
  192.         }
  193.         
  194.         /* 读出该地址的数据 */
  195.         for(i=0;i<8;i++)
  196.         {
  197.                 temp=temp>>1;
  198.                
  199.                 if(SDA_P)
  200.                         temp|= 0x80;
  201.                 else
  202.                         temp&=0x7F;
  203.                
  204.                 SCK_P=1;
  205.                 _nop_();
  206.                 SCK_P=0;
  207.                 _nop_();
  208.         }
  209.         
  210.         RST_P=0;
  211.         
  212.         return temp;
  213. }


  214. /*********************************************************/
  215. // 向DS1302写入一字节数据
  216. /*********************************************************/
  217. void DS1302_Write_Byte(uchar addr, uchar dat)
  218. {
  219.         uchar i;
  220.         
  221.         RST_P = 1;
  222.         
  223.         /* 写入目标地址:addr*/
  224.         for(i=0;i<8;i++)
  225.         {
  226.                 if(addr&0x01)
  227.                         SDA_P=1;
  228.                 else
  229.                         SDA_P=0;

  230.                 SCK_P=1;
  231.                 _nop_();
  232.                 SCK_P=0;
  233.                 _nop_();
  234.                
  235.                 addr=addr>>1;
  236.         }
  237.         
  238.         /* 写入数据:dat*/
  239.         for(i=0;i<8;i++)
  240.         {
  241.                 if(dat&0x01)
  242.                         SDA_P=1;
  243.                 else
  244.                         SDA_P=0;
  245.         
  246.                 SCK_P=1;
  247.                 _nop_();
  248.                 SCK_P=0;
  249.                 _nop_();
  250.                
  251.                 dat=dat>>1;
  252.         }
  253.         
  254.         RST_P=0;                                       
  255. }


  256. /*********************************************************/
  257. // 向DS1302写入时间数据
  258. /*********************************************************/
  259. void DS1302_Write_Time()
  260. {
  261.   uchar i;
  262.         uchar temp1;
  263.         uchar temp2;
  264.         
  265.         for(i=0;i<7;i++)                        // 十进制转BCD码
  266.         {
  267.                 temp1=(TimeBuff[i]/10)<<4;
  268.                 temp2=TimeBuff[i]%10;
  269.                 TimeBuff[i]=temp1+temp2;
  270.         }
  271.         
  272.         DS1302_Write_Byte(0x8E,0x00);                                                                // 关闭写保护
  273.         DS1302_Write_Byte(0x80,0x80);                                                                // 暂停时钟
  274.         DS1302_Write_Byte(0x8C,TimeBuff[0]);                                // 年
  275.         DS1302_Write_Byte(0x88,TimeBuff[1]);                                // 月
  276.         DS1302_Write_Byte(0x86,TimeBuff[2]);                                // 日
  277.         DS1302_Write_Byte(0x8A,TimeBuff[3]);                                // 星期
  278.         DS1302_Write_Byte(0x84,TimeBuff[4]);                                // 时
  279.         DS1302_Write_Byte(0x82,TimeBuff[5]);                                // 分
  280.         DS1302_Write_Byte(0x80,TimeBuff[6]);                                // 秒
  281.         DS1302_Write_Byte(0x80,TimeBuff[6]&0x7F);                // 运行时钟
  282.         DS1302_Write_Byte(0x8E,0x80);                                                                // 打开写保护  
  283. }



  284. /*********************************************************/
  285. // 从DS1302读出时间数据
  286. /*********************************************************/
  287. void DS1302_Read_Time()  
  288. {
  289.         uchar i;

  290.         TimeBuff[0]=DS1302_Read_Byte(0x8D);                                                // 年
  291.         TimeBuff[1]=DS1302_Read_Byte(0x89);                                                // 月
  292.         TimeBuff[2]=DS1302_Read_Byte(0x87);                                                // 日
  293.         TimeBuff[3]=DS1302_Read_Byte(0x8B);                                                // 星期
  294.         TimeBuff[4]=DS1302_Read_Byte(0x85);                                                // 时
  295.         TimeBuff[5]=DS1302_Read_Byte(0x83);                                                // 分
  296.         TimeBuff[6]=(DS1302_Read_Byte(0x81))&0x7F;                // 秒

  297.         for(i=0;i<7;i++)                // BCD转十进制
  298.         {           
  299.                 TimeBuff[i]=(TimeBuff[i]/16)*10+TimeBuff[i]%16;
  300.         }
  301. }


  302. /*********************************************************/
  303. // ADC0832的时钟脉冲
  304. /*********************************************************/
  305. void WavePlus()
  306. {
  307.         _nop_();
  308.         ADC_CLK = 1;
  309.         _nop_();
  310.         ADC_CLK = 0;
  311. }


  312. /*********************************************************/
  313. // 获取指定通道的A/D转换结果
  314. /*********************************************************/
  315. uchar Get_ADC0832()
  316. {
  317.         uchar i;
  318.         uchar dat1=0;
  319.         uchar dat2=0;
  320.         
  321.         ADC_CLK = 0;                                // 电平初始化
  322.         ADC_DAT = 1;
  323.         _nop_();
  324.         ADC_CS = 0;
  325.         WavePlus();                                        // 起始信号
  326.         ADC_DAT = 1;
  327.         WavePlus();                                        // 通道选择的第一位
  328.         ADC_DAT = 0;      
  329.         WavePlus();                                        // 通道选择的第二位
  330.         ADC_DAT = 1;
  331.         
  332.         for(i=0;i<8;i++)                // 第一次读取
  333.         {
  334.                 dat1<<=1;
  335.                 WavePlus();
  336.                 if(ADC_DAT)
  337.                         dat1=dat1|0x01;
  338.                 else
  339.                         dat1=dat1|0x00;
  340.         }
  341.         
  342.         for(i=0;i<8;i++)                // 第二次读取
  343.         {
  344.                 dat2>>= 1;
  345.                 if(ADC_DAT)
  346.                         dat2=dat2|0x80;
  347.                 else
  348.                         dat2=dat2|0x00;
  349.                 WavePlus();
  350.         }
  351.         
  352.         _nop_();                                                // 结束此次传输
  353.         ADC_DAT = 1;
  354.         ADC_CLK = 1;
  355.         ADC_CS  = 1;   

  356.         if(dat1==dat2)                        // 返回采集结果
  357.                 return dat1;
  358.         else
  359.                 return 0;
  360. }


  361. /*********************************************************/
  362. // 按键扫描(设置当前时间)
  363. /*********************************************************/
  364. void KeyScanf1()
  365. {
  366.         if(KeySet_P==0)
  367.         {
  368.                 LcdGotoXY(0,13);                                // 显示秒钟的冒号
  369.                 LcdWriteData(':');
  370.                 LcdWriteCmd(0x0f);                        // 启动光标闪烁
  371.                 LcdGotoXY(0,3);                                        // 定位光标到年份闪烁
  372.                 DelayMs(10);                                                // 延时等待,消除按键按下的抖动
  373.                 while(!KeySet_P);                                // 等待按键释放
  374.                 DelayMs(10);                                                // 延时等待,消除按键松开的抖动
  375.                
  376.                 /* 调整年份 */
  377.                 while(1)
  378.                 {
  379.                         if(KeyDown_P==0)                                                        // 如果减按键被下去
  380.                         {
  381.                                 if(TimeBuff[0]>0)                                                // 判断年份是否大于0               
  382.                                         TimeBuff[0]--;                                                // 是的话就减去1
  383.                                 LcdGotoXY(0,2);                                                        // 光标定位到年份的位置
  384.                                 LcdPrintNum(TimeBuff[0]);                // 刷新显示改变后的年份
  385.                                 LcdGotoXY(0,3);                                                        // 定位光标到年份闪烁
  386.                                 DelayMs(300);                                                                // 延时0.3秒左右
  387.                         }
  388.                         
  389.                         if(KeyUp_P==0)                                                                // 如果加按键被下去
  390.                         {
  391.                                 if(TimeBuff[0]<99)                                        // 判断年份是否小于99
  392.                                         TimeBuff[0]++;                                                // 是的话就加上1
  393.                                 LcdGotoXY(0,2);                                                        // 光标定位到年份的位置
  394.                                 LcdPrintNum(TimeBuff[0]);                // 刷新显示改变后的年份
  395.                                 LcdGotoXY(0,3);                                                        // 定位光标到年份闪烁
  396.                                 DelayMs(300);                                                                // 延时0.3秒左右
  397.                         }
  398.                         
  399.                         if(KeySet_P==0)
  400.                         {
  401.                                 break;
  402.                         }
  403.                 }
  404.                
  405.                 LcdGotoXY(0,6);                                        // 定位光标到月份闪烁
  406.                 DelayMs(10);                                                // 延时等待,消除按键按下的抖动
  407.                 while(!KeySet_P);                                // 等待按键释放
  408.                 DelayMs(10);                                                // 延时等待,消除按键松开的抖动
  409.                         
  410.                 /* 调整月份 */
  411.                 while(1)
  412.                 {
  413.                         if(KeyDown_P==0)                                                        // 如果减按键被下去
  414.                         {
  415.                                 if(TimeBuff[1]>1)                                                // 判断月份是否大于1               
  416.                                         TimeBuff[1]--;                                                // 是的话就减去1
  417.                                 LcdGotoXY(0,5);                                                        // 光标定位到月份的位置
  418.                                 LcdPrintNum(TimeBuff[1]);                // 刷新显示改变后的月份
  419.                                 LcdGotoXY(0,6);                                                        // 定位光标到月份闪烁
  420.                                 DelayMs(300);                                                                // 延时0.3秒左右
  421.                         }
  422.                         
  423.                         if(KeyUp_P==0)                                                                // 如果加按键被下去
  424.                         {
  425.                                 if(TimeBuff[1]<12)                                        // 判断月份是否小于12
  426.                                         TimeBuff[1]++;                                                // 是的话就加上1
  427.                                 LcdGotoXY(0,5);                                                        // 光标定位到月份的位置
  428.                                 LcdPrintNum(TimeBuff[1]);                // 刷新显示改变后的月份
  429.                                 LcdGotoXY(0,6);                                                        // 定位光标到月份闪烁
  430.                                 DelayMs(300);                                                                // 延时0.3秒左右
  431.                         }
  432.                         
  433.                         if(KeySet_P==0)
  434.                         {
  435.                                 break;
  436.                         }
  437.                 }
  438.                
  439.                 LcdGotoXY(0,9);                                        // 定位光标到日期闪烁
  440.                 DelayMs(10);                                                // 延时等待,消除按键按下的抖动
  441.                 while(!KeySet_P);                                // 等待按键释放
  442.                 DelayMs(10);                                                // 延时等待,消除按键松开的抖动
  443.                
  444.                 /* 调整日期 */
  445.                 while(1)
  446.                 {
  447.                         if(KeyDown_P==0)                                                        // 如果减按键被下去
  448.                         {
  449.                                 if(TimeBuff[2]>1)                                                // 判断日期是否大于1               
  450.                                         TimeBuff[2]--;                                                // 是的话就减去1
  451.                                 LcdGotoXY(0,8);                                                        // 光标定位到日期的位置
  452.                                 LcdPrintNum(TimeBuff[2]);                // 刷新显示改变后的日期
  453.                                 LcdGotoXY(0,9);                                                        // 定位光标到日期闪烁
  454.                                 DelayMs(300);                                                                // 延时0.3秒左右
  455.                         }
  456.                         
  457.                         if(KeyUp_P==0)                                                                // 如果加按键被下去
  458.                         {
  459.                                 if(TimeBuff[2]<31)                                        // 判断日期是否小于31
  460.                                         TimeBuff[2]++;                                                // 是的话就加上1
  461.                                 LcdGotoXY(0,8);                                                        // 光标定位到日期的位置
  462.                                 LcdPrintNum(TimeBuff[2]);                // 刷新显示改变后的日期
  463.                                 LcdGotoXY(0,9);                                                        // 定位光标到日期闪烁
  464.                                 DelayMs(300);                                                                // 延时0.3秒左右
  465.                         }
  466.                         
  467.                         if(KeySet_P==0)
  468.                         {
  469.                                 break;
  470.                         }
  471.                 }
  472.                
  473.                 LcdGotoXY(0,12);                                // 定位光标到小时闪烁
  474.                 DelayMs(10);                                                // 延时等待,消除按键按下的抖动
  475.                 while(!KeySet_P);                                // 等待按键释放
  476.                 DelayMs(10);                                                // 延时等待,消除按键松开的抖动
  477.                
  478.                
  479.                 /* 调整小时 */
  480.                 while(1)
  481.                 {
  482.                         if(KeyDown_P==0)                                                        // 如果减按键被下去
  483.                         {
  484.                                 if(TimeBuff[4]>0)                                                // 判断小时是否大于0
  485.                                         TimeBuff[4]--;                                                // 是的话就减去1
  486.                                 LcdGotoXY(0,11);                                                // 光标定位到小时的位置
  487.                                 LcdPrintNum(TimeBuff[4]);                // 刷新显示改变后的小时
  488.                                 LcdGotoXY(0,12);                                                // 定位光标到小时闪烁
  489.                                 DelayMs(300);                                                                // 延时0.3秒左右
  490.                         }
  491.                         
  492.                         if(KeyUp_P==0)                                                                // 如果加按键被下去
  493.                         {
  494.                                 if(TimeBuff[4]<23)                                        // 判断小时是否小于23
  495.                                         TimeBuff[4]++;                                                // 是的话就加上1
  496.                                 LcdGotoXY(0,11);                                                // 光标定位到小时的位置
  497.                                 LcdPrintNum(TimeBuff[4]);                // 刷新显示改变后的小时
  498.                                 LcdGotoXY(0,12);                                                // 定位光标到小时闪烁
  499.                                 DelayMs(300);                                                                // 延时0.3秒左右
  500.                         }
  501.                         
  502.                         if(KeySet_P==0)
  503.                         {
  504.                                 break;
  505.                         }
  506.                 }
  507.                
  508.                 LcdGotoXY(0,15);                                // 定位光标到分钟闪烁
  509.                 DelayMs(10);                                                // 延时等待,消除按键按下的抖动
  510.                 while(!KeySet_P);                                // 等待按键释放
  511.                 DelayMs(10);                                                // 延时等待,消除按键松开的抖动
  512.                
  513.                 /* 调整分钟 */
  514.                 while(1)
  515.                 {
  516.                         if(KeyDown_P==0)                                                        // 如果减按键被下去
  517.                         {
  518.                                 if(TimeBuff[5]>0)                                                // 判断分钟是否大于0
  519.                                         TimeBuff[5]--;                                                // 是的话就减去1
  520.                                 LcdGotoXY(0,14);                                                // 光标定位到分钟的位置
  521.                                 LcdPrintNum(TimeBuff[5]);                // 刷新显示改变后的分钟
  522.                                 LcdGotoXY(0,15);                                                // 定位光标到分钟闪烁
  523.                                 DelayMs(300);                                                                // 延时0.3秒左右
  524.                         }
  525.                         
  526.                         if(KeyUp_P==0)                                                                // 如果加按键被下去
  527.                         {
  528.                                 if(TimeBuff[5]<59)                                        // 判断分钟是否小于59
  529.                                         TimeBuff[5]++;                                                // 是的话就加上1
  530.                                 LcdGotoXY(0,14);                                                // 光标定位到分钟的位置
  531.                                 LcdPrintNum(TimeBuff[5]);                // 刷新显示改变后的分钟
  532.                                 LcdGotoXY(0,15);                                                // 定位光标到分钟闪烁
  533.                                 DelayMs(300);                                                                // 延时0.3秒左右
  534.                         }
  535.                         
  536.                         if(KeySet_P==0)
  537.                         {
  538.                                 break;
  539.                         }
  540.                 }
  541.                
  542.                 /* 退出前的设置 */
  543.                 LcdWriteCmd(0x0C);                        // 关闭光标闪烁
  544.                 DS1302_Write_Time();                // 把新设置的时间值存入DS1302芯片
  545.                 DelayMs(10);                                                // 延时等待,消除按键按下的抖动
  546.                 while(!KeySet_P);                                // 等待按键释放
  547.                 DelayMs(10);                                                // 延时等待,消除按键松开的抖动
  548.         }
  549. }


  550. /*********************************************************/
  551. // 按键扫描(设置窗帘的动作)
  552. /*********************************************************/
  553. void KeyScanf2()
  554. {
  555.         if(KeySet2_P==0)
  556.         {
  557.                 LcdGotoXY(0,0);                                                                                // 光标定位
  558.                 LcdPrintStr(" OpenTime   :   ");        // 显示第1行内容
  559.                 LcdGotoXY(1,0);                                                                                // 光标定位
  560.                 LcdPrintStr("CloseTime   :   ");        // 显示第2行内容
  561.                 LcdGotoXY(0,10);                                                                        // 光标定位
  562.                 LcdPrintNum(OpenHour);                                                // 显示开启窗帘的小时
  563.                 LcdGotoXY(0,13);                                                                        // 光标定位
  564.                 LcdPrintNum(OpenMinute);                                        // 显示开启窗帘的分钟
  565.                 LcdGotoXY(1,10);                                                                        // 光标定位
  566.                 LcdPrintNum(CloseHour);                                                // 显示关闭窗帘的小时
  567.                 LcdGotoXY(1,13);                                                                        // 光标定位
  568.                 LcdPrintNum(CloseMinute);                                        // 显示关闭窗帘的分钟               
  569.                
  570.                 LcdWriteCmd(0x0f);                                                        // 启动光标闪烁
  571.                 LcdGotoXY(0,11);                                                                // 定位光标
  572.                 DelayMs(10);                                                                                // 延时等待,消除按键按下的抖动
  573.                 while(!KeySet2_P);                                                        // 等待按键释放
  574.                 DelayMs(10);                                                                                // 延时等待,消除按键松开的抖动
  575.                
  576.                 /* 调整开启的小时 */
  577.                 while(1)
  578.                 {
  579.                         if(KeyDown_P==0)                                                        // 如果减按键被下去
  580.                         {
  581.                                 if(OpenHour>0)                                                        // 判断小时是否大于0               
  582.                                         OpenHour--;                                                                // 是的话就减去1
  583.                                 LcdGotoXY(0,10);                                                // 光标定位
  584.                                 LcdPrintNum(OpenHour);                        // 刷新显示改变后的小时
  585.                                 LcdGotoXY(0,11);                                                // 定位光标
  586.                                 DelayMs(300);                                                                // 延时0.3秒左右
  587.                         }
  588.                         
  589.                         if(KeyUp_P==0)                                                                // 如果加按键被下去
  590.                         {
  591.                                 if(OpenHour<23)                                                        // 判断小时是否小于23
  592.                                         OpenHour++;                                                                // 是的话就加上1
  593.                                 LcdGotoXY(0,10);                                                // 光标定位
  594.                                 LcdPrintNum(OpenHour);                        // 刷新显示改变后的小时
  595.                                 LcdGotoXY(0,11);                                                // 定位光标
  596.                                 DelayMs(300);                                                                // 延时0.3秒左右
  597.                         }
  598.                         
  599.                         if(KeySet2_P==0)
  600.                         {
  601.                                 break;
  602.                         }
  603.                 }
  604.                
  605.                 LcdGotoXY(0,14);                                                                // 定位光标
  606.                 DelayMs(10);                                                                                // 延时等待,消除按键按下的抖动
  607.                 while(!KeySet2_P);                                                        // 等待按键释放
  608.                 DelayMs(10);                                                                                // 延时等待,消除按键松开的抖动
  609.                
  610.                 /* 调整开启的分钟 */
  611.                 while(1)
  612.                 {
  613.                         if(KeyDown_P==0)                                                        // 如果减按键被下去
  614.                         {
  615.                                 if(OpenMinute>0)                                                // 判断分钟是否大于0
  616.                                         OpenMinute--;                                                        // 是的话就减去1
  617.                                 LcdGotoXY(0,13);                                                // 光标定位
  618.                                 LcdPrintNum(OpenMinute);                // 刷新显示改变后的分钟
  619.                                 LcdGotoXY(0,14);                                                // 定位光标
  620.                                 DelayMs(300);                                                                // 延时0.3秒左右
  621.                         }
  622.                         
  623.                         if(KeyUp_P==0)                                                                // 如果加按键被下去
  624.                         {
  625.                                 if(OpenMinute<59)                                                // 判断分钟是否小于59
  626.                                         OpenMinute++;                                                        // 是的话就加上1
  627.                                 LcdGotoXY(0,13);                                                // 光标定位
  628.                                 LcdPrintNum(OpenMinute);                // 刷新显示改变后的分钟
  629.                                 LcdGotoXY(0,14);                                                // 定位光标
  630.                                 DelayMs(300);                                                                // 延时0.3秒左右
  631.                         }
  632.                         
  633.                         if(KeySet2_P==0)
  634.                         {
  635.                                 break;
  636.                         }
  637.                 }
  638.                
  639.                 LcdGotoXY(1,11);                                                                // 定位光标
  640.                 DelayMs(10);                                                                                // 延时等待,消除按键按下的抖动
  641.                 while(!KeySet2_P);                                                        // 等待按键释放
  642.                 DelayMs(10);                                                                                // 延时等待,消除按键松开的抖动
  643.                
  644.                 /* 调整关闭的小时 */
  645.                 while(1)
  646.                 {
  647.                         if(KeyDown_P==0)                                                        // 如果减按键被下去
  648.                         {
  649.                                 if(CloseHour>0)                                                        // 判断小时是否大于0               
  650.                                         CloseHour--;                                                        // 是的话就减去1
  651.                                 LcdGotoXY(1,10);                                                // 光标定位
  652.                                 LcdPrintNum(CloseHour);                        // 刷新显示改变后的小时
  653.                                 LcdGotoXY(1,11);                                                // 定位光标
  654.                                 DelayMs(300);                                                                // 延时0.3秒左右
  655.                         }
  656.                         
  657.                         if(KeyUp_P==0)                                                                // 如果加按键被下去
  658.                         {
  659.                                 if(CloseHour<23)                                                // 判断小时是否小于23
  660.                                         CloseHour++;                                                        // 是的话就加上1
  661.                                 LcdGotoXY(1,10);                                                // 光标定位
  662.                                 LcdPrintNum(CloseHour);                        // 刷新显示改变后的小时
  663.                                 LcdGotoXY(1,11);                                                // 定位光标
  664.                                 DelayMs(300);                                                                // 延时0.3秒左右
  665.                         }
  666.                         
  667.                         if(KeySet2_P==0)
  668.                         {
  669.                                 break;
  670.                         }
  671.                 }
  672.                
  673.                 LcdGotoXY(1,14);                                                                // 定位光标
  674.                 DelayMs(10);                                                                                // 延时等待,消除按键按下的抖动
  675.                 while(!KeySet2_P);                                                        // 等待按键释放
  676.                 DelayMs(10);                                                                                // 延时等待,消除按键松开的抖动
  677.                
  678.                 /* 调整关闭的分钟 */
  679.                 while(1)
  680.                 {
  681.                         if(KeyDown_P==0)                                                        // 如果减按键被下去
  682.                         {
  683.                                 if(CloseMinute>0)                                                // 判断分钟是否大于0
  684.                                         CloseMinute--;                                                // 是的话就减去1
  685.                                 LcdGotoXY(1,13);                                                // 光标定位
  686.                                 LcdPrintNum(CloseMinute);                // 刷新显示改变后的分钟
  687.                                 LcdGotoXY(1,14);                                                // 定位光标
  688.                                 DelayMs(300);                                                                // 延时0.3秒左右
  689.                         }
  690.                         
  691.                         if(KeyUp_P==0)                                                                // 如果加按键被下去
  692.                         {
  693.                                 if(CloseMinute<59)                                        // 判断分钟是否小于59
  694.                                         CloseMinute++;                                                // 是的话就加上1
  695.                                 LcdGotoXY(1,13);                                                // 光标定位
  696.                                 LcdPrintNum(CloseMinute);                // 刷新显示改变后的分钟
  697.                                 LcdGotoXY(1,14);                                                // 定位光标
  698.                                 DelayMs(300);                                                                // 延时0.3秒左右
  699.                         }
  700.                         
  701.                         if(KeySet2_P==0)
  702.                         {
  703.                                 break;
  704.                         }
  705.                 }
  706.                
  707.                 DelayMs(10);                                                                                // 延时等待,消除按键按下的抖动
  708.                 while(!KeySet2_P);                                                        // 等待按键释放
  709.                 DelayMs(10);                                                                                // 延时等待,消除按键松开的抖动
  710.                
  711.                 /* 光照强度的设置 */
  712.         //        LcdWriteCmd(0x0C);                                                                // 关闭光标闪烁
  713.                 LcdGotoXY(0,0);                                                                                // 光标定位
  714.                 LcdPrintStr("   Light Set    ");        // 显示第1行内容
  715.                 LcdGotoXY(1,0);                                                                                // 光标定位
  716.                 LcdPrintStr(" L:      H:     ");        // 显示第2行内容
  717.                 LcdGotoXY(1,3);                                                                                // 光标定位
  718.                 LcdPrintNum(gLight);                                                        // 显示窗帘的光线控制强度阈值
  719.                 LcdGotoXY(1,4);
  720.                 LcdGotoXY(1,11);                                                                                // 光标定位
  721.                 LcdPrintNum(gLightmax);                                                        // 显示窗帘的光线控制强度阈值
  722.                 LcdGotoXY(1,4);
  723.                 while(1)
  724.                 {
  725.                         if(KeyDown_P==0)                                                        // 如果减按键被下去
  726.                         {
  727.                                 if(gLight>0)                                                                // 判断光线阈值是否大于0
  728.                                         gLight--;                                                                        // 是的话就减去1
  729.                                 LcdGotoXY(1,3);                                                                                // 光标定位
  730.                                 LcdPrintNum(gLight);                                                        // 显示窗帘的光线控制强度阈值
  731.                                 LcdGotoXY(1,4);
  732.                                 DelayMs(300);                                                                // 延时0.3秒左右
  733.                         }
  734.                         
  735.                         if(KeyUp_P==0)                                                                // 如果加按键被下去
  736.                         {
  737.                                 if(gLight<99)                                                                // 判断光线阈值是否小于59
  738.                                         gLight++;                                                                        // 是的话就加上1
  739.                                 LcdGotoXY(1,3);                                                                                // 光标定位
  740.                                 LcdPrintNum(gLight);                                                        // 显示窗帘的光线控制强度阈值
  741.                                 LcdGotoXY(1,4);
  742.                                 DelayMs(300);                                                                // 延时0.3秒左右
  743.                         }
  744.                         
  745.                         if(KeySet2_P==0)
  746.                         {
  747.                                 break;
  748.                         }
  749.                 }
  750.                 DelayMs(10);                                                                                // 延时等待,消除按键按下的抖动
  751.                 while(!KeySet2_P);                                                        // 等待按键释放
  752.                 DelayMs(10);                                                                                // 延时等待,消除按键松开的抖动
  753.                
  754.                 /* 光照强度的设置 */
  755.         
  756.                 LcdGotoXY(1,11);                                                                                // 光标定位
  757.                 LcdPrintNum(gLightmax);                                                        // 显示窗帘的光线控制强度阈值
  758.                 LcdGotoXY(1,12);
  759.                 while(1)
  760.                 {
  761.                         if(KeyDown_P==0)                                                        // 如果减按键被下去
  762.                         {
  763.                                 if(gLight>0)                                                                // 判断光线阈值是否大于0
  764.                                         gLightmax--;                                                                        // 是的话就减去1
  765.                                 LcdGotoXY(1,11);                                                                                // 光标定位
  766.                                 LcdPrintNum(gLightmax);                                                        // 显示窗帘的光线控制强度阈值
  767.                                 LcdGotoXY(1,12);
  768.                                 DelayMs(300);                                                                // 延时0.3秒左?
  769.                         }
  770.                         
  771.                         if(KeyUp_P==0)                                                                // 如果加按键被下去
  772.                         {
  773.                                 if(gLight<99)                                                                // 判断光线阈值是否小于59
  774.                                         gLightmax++;                                                                        // 是的话就加上1
  775.                                 LcdGotoXY(1,11);                                                                                // 光标定位
  776.                                 LcdPrintNum(gLightmax);                                                        // 显示窗帘的光线控制强度阈值
  777.                                 LcdGotoXY(1,12);
  778.                                 DelayMs(300);                                                                // 延时0.3秒左右
  779.                         }
  780.                         
  781.                         if(KeySet2_P==0)
  782.                         {
  783.                                 break;
  784.                         }
  785.                 }
  786.                  LcdWriteCmd(0x0C);
  787.                 /* 退出前的设置 */
  788.                 LcdShowInit();                                        // 液晶显示内容初始化
  789.                 DelayMs(10);                                                // 延时等待,消除按键按下的抖动
  790.                 while(!KeySet2_P);                        // 等待按键释放
  791.                 DelayMs(10);                                                // 延时等待,消除按键松开的抖动
  792.         }
  793. }


  794. /*********************************************************/
  795. // 按键扫描(模式切换)
  796. /*********************************************************/
  797. void KeyScanf3()
  798. {
  799.         if(KeyMode_P==0)
  800.         {
  801.                 gMode++;                                                        // 切换到下一模式
  802.                 if(gMode==4)                                        // 如果到尽头了
  803.                         gMode=1;                                                // 回到第一种模式
  804.                 LcdGotoXY(1,0);                                // 光标定位
  805.                 LcdPrintMode(gMode);        // 显示模式
  806.                 DelayMs(10);                                        // 去除按键按下的抖动
  807.                 while(!KeyMode_P);                // 等待按键是否
  808.                 DelayMs(10);                                        // 去除按键松开的抖动
  809.         }
  810. }


  811. /*********************************************************/
  812. // 开窗
  813. /*********************************************************/
  814. void Open()
  815. {
  816.         uint i,j;
  817.         for(j=0;j<255;j++)                // 控制步进电机正转
  818.         {
  819.                 for(i=0;i<4;i++)
  820.                 {
  821.                         P2=Clock[i];
  822.                         DelayMs(3);
  823.                 }
  824.         }
  825.         Led_P=0;
  826. }



  827. /*********************************************************/
  828. // 关窗
  829. /*********************************************************/
  830. void Close()
  831. {
  832.         uint i,j;
  833.         for(j=0;j<255;j++)                // 控制步进电机反转
  834.         {
  835.                 for(i=0;i<4;i++)
  836.                 {
  837.                         P2=AntiClock[i];
  838.                         DelayMs(3);
  839.                 }
  840.         }
  841.         Led_P=1;
  842. }



  843. /*********************************************************/
  844. // 主函数
  845. /*********************************************************/
  846. void main()
  847. {
  848.         uchar light;
  849.         
  850.         LcdInit();                        // 执行液晶初始化        
  851.         DS1302_Init();        // 时钟芯片的初始化
  852.         LcdShowInit();        // 液晶显示内容的初始化
  853.         
  854.         if(DS1302_Read_Byte(0x81)>=128)                        // 判断时钟芯片是否正在运行
  855.         {
  856.                 DS1302_Write_Time();                                                        // 如果没有,则初始化一个时间
  857.         }
  858.         
  859.         while(1)
  860.         {
  861.                 DS1302_Read_Time();                                // 获取当前时钟芯片的时间,存在数组time_buf中
  862.                 FlashTime();                                                        // 刷新时间显示

  863.                 light=Get_ADC0832();                        // 读取光照强度
  864.                 light=light/2.5;                                        // 缩小光照检测结果(在0-99)
  865.                 if(light>99)                                                        // 如果大于99
  866.                         light=99;                                                                // 则依然保持99
  867.                 LcdGotoXY(1,14);                                        // 光标定位
  868.                 LcdPrintNum(light);                                // 显示光照强度
  869.                
  870.                 KeyScanf1();                                                        // 按键扫描(时间的设置)
  871.                 KeyScanf2();                                                        // 按键扫描(阈值的设置)
  872.                 KeyScanf3();                                                        // 按键扫描(模式切换)
  873.         
  874.                 /*手动控制模式*/
  875.                 if(gMode==1||YYOPEN==0)
  876.                 {
  877.                         if(KeyDown_P==0)                // 如果关窗帘键按下了        
  878.                         {
  879.                                 if(Led_P==0)                        // 如果窗帘当前是打开的
  880.                                 {
  881.                                         Close();                                // 则光标窗帘
  882.                                 }
  883.                         }
  884.                         if(KeyUp_P==0)                        // 如果开窗帘键按下了
  885.                         {
  886.                                 if(Led_P==1)                        // 如果窗帘当前是关闭的
  887.                                 {
  888.                                         Open();                                        // 则打开窗帘
  889.                                 }
  890.                         }        
  891.                 }

  892.                 /*时间控制模式*/
  893.                 if(gMode==2)
  894.                 {
  895.                         if((TimeBuff[4]==CloseHour)&&(TimeBuff[5]==CloseMinute)&&(TimeBuff[6]==0))        // 如果到了关窗帘的时间        
  896.                         {
  897.                                 if(Led_P==0)                        // 如果窗帘当前是打开的
  898.                                 {
  899.                                         Close();                                // 则光标窗帘
  900.                                 }
  901.                         }
  902.                         if((TimeBuff[4]==OpenHour)&&(TimeBuff[5]==OpenMinute)&&(TimeBuff[6]==0))                // 如果到了开窗帘的时间        
  903.                         {
  904.                                 if(Led_P==1)                        // 如果窗帘当前是关闭的
  905.                                 {
  906.                                         Open();                                        // 则打开窗帘
  907.                                 }
  908.                         }        
  909.                 }
  910.                
  911.                 /*光线控制模式*/
  912.                 if(gMode==3)
  913.                 {
  914.                         if(light<gLight || light>gLightmax)                // 当前光线小于设置的阈值
  915.                         {
  916.                                 if(Led_P==0)                        // 如果窗帘当前是打开的
  917.                                 {
  918.                                         Close();                                // 则光标窗帘
  919.                                 }
  920.                         }
  921.                         else                                                                // 当前光线大于或等于设置的阈值
  922.                         {
  923.                                 if(Led_P==1)                        // 如果窗帘当前是关闭的
  924.                                 {
  925.                                         Open();                                        // 则打开窗帘
  926.                                 }
  927.                         }        
  928.                 }
  929.                
  930.                 DelayMs(100);                                                        // 延时0.1秒
  931.         }
  932. }

复制代码

仿真程序: 智能窗帘.zip (293.27 KB, 下载次数: 46)

评分

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

查看全部评分

回复

使用道具 举报

ID:34149 发表于 2024-6-8 21:26 | 显示全部楼层
编写这么长的代码,实属不易,谢谢楼主的分享。
回复

使用道具 举报

ID:1122159 发表于 2024-6-9 13:21 | 显示全部楼层
dyx811 发表于 2024-6-8 21:26
编写这么长的代码,实属不易,谢谢楼主的分享。

哈哈,没事
回复

使用道具 举报

ID:496636 发表于 2024-6-10 07:50 | 显示全部楼层
拷贝到工程里,编译成功,零错误,零警告,注释也太详尽了,谢谢楼主
回复

使用道具 举报

ID:1122580 发表于 2024-6-10 10:25 | 显示全部楼层
感谢楼主,这么长得代码,学习了。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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