电路原理图如下:
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
单片机源程序如下:
- /*************************************************************
- 智能窗帘
- 补充说明:
- ***************************************************************/
- #include<reg52.h> //头文件
- #include<LCD1602.h>
- #include<DS1302.h>
- #include<28BYJ48.h>
- #include<EEPROM.h>
- #include<ADC0832.h>
- #include<HW.h>
- #define uchar unsigned char//宏定义
- #define uint unsigned int
- /*******************引脚定义*********************/
- sbit key_mode = P1^0; //设置键
- sbit key_jia = P1^1; //加值键
- sbit key_jian = P1^2; //减值键
- sbit key_ok = P1^3; //确定键
- sbit sw1=P3^7; //全开 限位开关
- sbit sw2=P3^6; //全关 限位开关
- /*******************变量定义*********************/
- uchar light_up,light_down;//存储光强上、下限值
- uchar set_f=0; //设置选择标记,=0非设置,=1设置年,=2设置月,=3设置日,=4设置时,=5设置分,=6设置秒
- // =7设置定时-时,=8设置定时-分,=9设置定时-开关,=10设置窗帘打开/关闭
- // =11设置光强上限,=12设置光强下限,=13设置校准窗帘位置
- uchar num; //计数变量
- uchar ds[4]; //定时控制开时、分、控制关时、分
- uchar mode=0; //模式标记。=0手动,=1定时,=2光控
- uchar light; //存储光强
- uint moto_num=0; //记录窗帘位置
- uchar moto_state=0;//窗帘状态,=0已经关闭,=1处于运转过程中,=2已经打开
- bit moto_f=0; //标记当前控制状态,=0控制关,=1控制开
- uchar code display_mode[3][3]={"SD\0","DS\0","GK\0"};//显示模式
- /********************************************************
- 函数名称:void delayms(uint ms)
- 函数作用:毫秒延时函数
- 参数说明:
- ********************************************************/
- void delayms(uint ms)
- {
- unsigned char i=100,j;
- for(;ms;ms--)
- {
- while(--i)
- {
- j=10;
- while(--j);
- }
- }
- }
- /********************************************************
- 函数名称:void display(void)
- 函数作用:正常显示日期、时间、光强等函数
- 参数说明:
- ********************************************************/
- void display(void)
- {
- uint t[3];
- //显示时间
- LCD_disp_char(0,2,ASCII[time[2]/10]);//显示时【0:表示第1列,2:表示第2行,所有关于显示都一样】
- LCD_disp_char(1,2,ASCII[time[2]%10]);
- LCD_disp_char(2,2,':');
- LCD_disp_char(3,2,ASCII[time[1]/10]);//显示分【3:表示第4列,2:表示第2行,所有关于显示都一样】
- LCD_disp_char(4,2,ASCII[time[1]%10]);
- LCD_disp_char(5,2,':');
- LCD_disp_char(6,2,ASCII[time[0]/10]);//显示秒
- LCD_disp_char(7,2,ASCII[time[0]%10]);
- //显示日期
- LCD_disp_char(0,1,ASCII[time[6]/10]);//显示年
- LCD_disp_char(1,1,ASCII[time[6]%10]);
- LCD_disp_char(2,1,'/');
- LCD_disp_char(3,1,ASCII[time[4]/10]);//显示月
- LCD_disp_char(4,1,ASCII[time[4]%10]);
- LCD_disp_char(5,1,'/');
- LCD_disp_char(6,1,ASCII[time[3]/10]);//显示日
- LCD_disp_char(7,1,ASCII[time[3]%10]);
- //显示模式
- lcd1602_write_character(9,1,display_mode[mode]);
-
- //显示光强
- if(light>99)
- LCD_disp_char(12,1,ASCII[light/100]);
- else
- LCD_disp_char(12,1,' ');
- LCD_disp_char(13,1,ASCII[light%100/10]);
- LCD_disp_char(14,1,ASCII[light%10]);
- LCD_disp_char(15,1,'%');
- //光强控制
- if(mode==2)//光控模式
- {
- if((light>=light_up||light<light_down))//判断实际光强是否【大于等于上限 或 小于下限值】、当前处于打开状态
- {
- moto_f=0; //标记当前控制窗帘关闭
- moto_state=1;//标记窗帘处于运转过程中
- }
- else
- if((light<light_up&&light>=light_down))//判断实际光强是否【大于等于下限值 并且 小于上限】、当前处于关闭状态
- {
- moto_f=1; //标记当前控制窗帘打开
- moto_state=1;//标记窗帘处于运转过程中
- }
- }
- else
- if(mode==1)//定时模式
- {
- t[0]=time[2]*60+time[1];//当前时间
- t[1]=ds[0]*60+ds[1]; //窗帘开启时间点
- t[2]=ds[2]*60+ds[3]; //窗帘关闭时间点
-
- if(t[1]<t[2]) //0时 --> t[1] --> t[2] --> 24时
- {
- if(t[0]>=t[1]&&t[0]<=t[2])
- moto_f=1; //标记当前需要打开窗帘
- else
- moto_f=0; //标记当前需要关闭窗帘
- }
- else //0时 --> t[2] --> t[1] --> 24时
- {
- if(t[0]>=t[1]||t[0]<=t[2])
- moto_f=1; //标记当前需要打开窗帘
- else
- moto_f=0; //标记当前需要关闭窗帘
- }
- moto_state=1; //标记窗帘处于运转过程中
- }
- if(moto_f==0&&moto_state!=0&&sw2!=0)//控制关闭窗帘
- {
- if(moto_num==0) //控制次数减到0时,表示窗户已经关闭完成
- {
- BYJ48=P2&0xf0; //关闭步进电机
- moto_state=0; //标记窗帘处于关闭状态
- lcd1602_write_character(10,2,"ZT:OFF");
- }
- else
- {
- motor_z(); //步进电机正转
- moto_num--; //控制次数-1
- lcd1602_write_character(10,2,"-->OFF");
- }
- }
- else
- if(moto_f==1&&moto_state!=2&&sw1!=0)//控制打开窗帘
- {
- if(moto_num>=192) //控制次数加到128时,表示窗户已经打开完成
- {
- BYJ48=P2&0xf0; //关闭步进电机
- moto_state=2; //标记窗帘处于打开状态
- lcd1602_write_character(10,2,"ZT:ON ");
- }
- else
- {
- motor_f(); //步进电机反转
- moto_num++; //控制次数+1
- lcd1602_write_character(10,2,"-->ON ");
- }
- }
- else //窗户处于停止状态
- {
- BYJ48=P2&0xf0; //关闭步进电机
- if(moto_state==0||sw2==0)
- lcd1602_write_character(10,2,"ZT:OFF");
- else
- if(moto_state==2||sw1==0)
- lcd1602_write_character(10,2,"ZT:ON ");
- }
- }
- /********************************************************
- 函数名称:void display2(void)
- 函数作用:显示调整日期、时间函数
- 参数说明:
- ********************************************************/
- void display2()
- {
- num++;
- lcd1602_write_character(1,1,"Date:");
- lcd1602_write_character(1,2,"Time:");
-
- if(num%2==0) //偶数次显示,奇数次不显示。这样就会有闪烁效果,可以清楚看到当前设置的是哪个值
- {
- LCD_disp_char(6,1,ASCII[time[6]/10]); //显示年
- LCD_disp_char(7,1,ASCII[time[6]%10]);
- LCD_disp_char(8,1,'/');
- LCD_disp_char(9,1,ASCII[time[4]/10]); //显示月
- LCD_disp_char(10,1,ASCII[time[4]%10]);
- LCD_disp_char(11,1,'/');
- LCD_disp_char(12,1,ASCII[time[3]/10]);//显示日
- LCD_disp_char(13,1,ASCII[time[3]%10]);
-
- LCD_disp_char(6,2,ASCII[time[2]/10]); //显示时
- LCD_disp_char(7,2,ASCII[time[2]%10]);
- LCD_disp_char(8,2,':');
- LCD_disp_char(9,2,ASCII[time[1]/10]); //显示分
- LCD_disp_char(10,2,ASCII[time[1]%10]);
- LCD_disp_char(11,2,':');
- LCD_disp_char(12,2,ASCII[time[0]/10]);//显示秒
- LCD_disp_char(13,2,ASCII[time[0]%10]);
- }
- else //奇数次不显示
- {
- switch(set_f)//根据当前设置的内容,对应位置闪烁
- {
- case 1: lcd1602_write_character(6,1," "); break;
- case 2: lcd1602_write_character(9,1," "); break;
- case 3: lcd1602_write_character(12,1," "); break;
- case 4: lcd1602_write_character(6,2," "); break;
- case 5: lcd1602_write_character(9,2," "); break;
- case 6: lcd1602_write_character(12,2," "); break;
- default: break;
- }
- }
- }
- /********************************************************
- 函数名称:void display3(void)
- 函数作用:显示调整定时时间函数
- 参数说明:
- ********************************************************/
- void display3()
- {
- num++;
- lcd1602_write_character(0, 1, "Sets timer time:");
- lcd1602_write_character(7, 2, "--");
- if(num%2==0) //偶数次显示,奇数次不显示。这样就会有闪烁效果,可以清楚看到当前设置的是哪个值
- {
- LCD_disp_char(1, 2, ASCII[ds[0]/10]); //显示定时开-时
- LCD_disp_char(2, 2, ASCII[ds[0]%10]);
- LCD_disp_char(3, 2, ':');
- LCD_disp_char(4, 2, ASCII[ds[1]/10]); //显示定时开-分
- LCD_disp_char(5, 2, ASCII[ds[1]%10]);
- LCD_disp_char(10, 2, ASCII[ds[2]/10]); //显示定时关-时
- LCD_disp_char(11, 2, ASCII[ds[2]%10]);
- LCD_disp_char(12, 2, ':');
- LCD_disp_char(13, 2, ASCII[ds[3]/10]); //显示定时关-分
- LCD_disp_char(14, 2, ASCII[ds[3]%10]);
- }
- else //奇数次不显示
- {
- switch(set_f)//根据当前设置的内容,对应位置闪烁
- {
- case 7: lcd1602_write_character(1,2," "); break;
- case 8: lcd1602_write_character(4,2," "); break;
- case 9: lcd1602_write_character(10,2," "); break;
- case 10: lcd1602_write_character(13,2," "); break;
- default: break;
- }
- }
- }
- /********************************************************
- 函数名称:void display4(void)
- 函数作用:显示调整光强控制函数
- 参数说明:
- ********************************************************/
- void display4(void)
- {
- num++;
- lcd1602_write_character(0, 1, "Light_Up :");
- lcd1602_write_character(0, 2, "Light_Down:");
- LCD_disp_char(15,1,'%');
- LCD_disp_char(15,2,'%');
- if(num%2==0) //偶数次显示,奇数次不显示。这样就会有闪烁效果,可以清楚看到当前设置的是哪个值
- {
- LCD_disp_char(12, 1, ASCII[light_up/100]); //显示光强上限值
- LCD_disp_char(13, 1, ASCII[light_up%100/10]);
- LCD_disp_char(14, 1, ASCII[light_up%10]);
-
- LCD_disp_char(12, 2, ASCII[light_down/100]); //显示光强下限值
- LCD_disp_char(13, 2, ASCII[light_down%100/10]);
- LCD_disp_char(14, 2, ASCII[light_down%10]);
- }
- else //奇数次不显示
- {
- switch(set_f)//根据当前设置的内容,对应位置闪烁
- {
- case 11: lcd1602_write_character(12,1," "); break;
- case 12: lcd1602_write_character(12,2," "); break;
- default: break;
- }
- }
- }
- /********************************************************
- 函数名称:void scan(void)
- 函数作用:按键查询处理函数
- 参数说明:
- ********************************************************/
- void scan(void)
- {
- //设置键
- if(hw_data=='B'||key_mode==0) //按键按下
- {
- delayms(7); //延时消抖
- if(hw_data=='B'||key_mode==0) //再次确认按键按下
- {
- BYJ48=P2&0xf0; //关闭步进电机
- if(set_f==6) //日期、时间校准完
- {
- LCD_write_command(0x01);//清除屏幕显示
- delay_n40us(100); //延时等待全部清除完毕
- set_f=13; //跳到校准窗帘状态
- }
- else
- if(set_f==0) //进入设置先清除屏幕,显示设置部分
- {
- Writeds1302 (WRITE_PROTECT,0X00);//禁止DS1302写保护
- LCD_write_command(0x01); //清除屏幕显示
- delay_n40us(100); //延时等待全部清除完毕
- switch(mode)//根据对应的模式,设置对应的参数
- {
- case 0: set_f=1; break; //手动模式
- case 1: set_f=7; break; //定时模式
- case 2: set_f=11; break; //光控模式
- default: break;
- }
- }
- else
- if(set_f==10||set_f==12)//进入设置日期时间
- {
- LCD_write_command(0x01); //清除屏幕显示
- delay_n40us(100); //延时等待全部清除完毕
- set_f=1; //进入校准时间
- }
- else
- set_f++; //设置变量+1
- if(set_f>12)
- {
- set_f=0; //重置设置变量
- Writeds1302 (WRITE_MINUTE,(time[1]/10)*16+time[1]%10);//将设置好的时间写入DS1302
- Writeds1302 (WRITE_SECOND,(time[0]/10)*16+time[0]%10);
- EEPROM_delete(0x2200); //擦除扇区
- EEPROM_write(0x2200,ds[0]); //写入【定时时间】数据保存
- EEPROM_write(0x2210,ds[1]); //写入【定时时间】数据保存存
- EEPROM_write(0x2220,ds[2]); //写入【定时时间】数据保存存
- EEPROM_write(0x2230,ds[3]); //写入【定时时间】数据保存存
- EEPROM_write(0x2240,light_up); //写入【光强上限值】数据保存
- EEPROM_write(0x2250,light_down);//写入【光强下限值】数据保存
- LCD_write_command(0x01); //清除屏幕显示
- delay_n40us(100); //延时等待全部清除完毕
- }
- }
- while(!key_mode); //等待按键松开
- }
- //确定
- if(hw_data=='Q'||key_ok==0) //按键按下
- {
- delayms(7); //延时消抖
- if((hw_data=='Q'||key_ok==0)&&set_f!=0)//再次确认按键按下
- {
- if(set_f<7)
- {
- Writeds1302 (WRITE_MINUTE,(time[1]/10)*16+time[1]%10);//将设置好的时间写入DS1302
- Writeds1302 (WRITE_SECOND,(time[0]/10)*16+time[0]%10);
- }
- set_f=0; //重置设置变量
-
- EEPROM_delete(0x2200); //擦除扇区
- EEPROM_write(0x2200,ds[0]); //写入【定时时间】数据保存
- EEPROM_write(0x2210,ds[1]); //写入【定时时间】数据保存存
- EEPROM_write(0x2220,ds[2]); //写入【定时时间】数据保存存
- EEPROM_write(0x2230,ds[3]); //写入【定时时间】数据保存存
- EEPROM_write(0x2240,light_up); //写入【光强上限值】数据保存
- EEPROM_write(0x2250,light_down);//写入【光强下限值】数据保存
- LCD_write_command(0x01); //清除屏幕显示
- delay_n40us(100); //延时等待全部清除完毕
- }
- else
- if(key_ok==0&&set_f==0) //切换模式
- {
- mode++; //模式变量+1
- if(mode>=3) //最大3个模式
- mode=0; //重新回到第1个模式
- if(moto_state==1) //如果处于运转过程中
- {
- if(moto_f==0) //控制步进电机关闭
- moto_state=0;
- else //控制步进电机打开
- moto_state=2;
- }
- EEPROM_delete(0x2400); //擦除扇区
- EEPROM_write(0x2400,mode); //写入【模式】数据保存
- }
- while(!key_ok); //等待按键松开
- }
- //加键 ,下面减键内容一样
- if(hw_data=='+'||key_jia==0)
- {
- delayms(7);
- if((hw_data=='+'||key_jia==0)&&set_f!=0)
- {
- if(set_f==1) //设置年
- {
- time[6]++; //年份+1
- time[6]=(time[6]/10)*16+time[6]%10; //将年份转换成16进制,例如:16年-->0x16
- if(time[6]>0x79) //判断是否达到最大年份79年
- time[6]=0x00; //重新回到00年
- Writeds1302 (WRITE_YEA,time[6]); //将设置好的年份写入到DS1302存储起来
- }
-
- if(set_f==2) //设置月
- {
- time[4]++; //月份+1
- time[4]=(time[4]/10)*16+time[4]%10; //将月份转换成16进制,例如:08月-->0x08
- if(time[4]>0x12) //判断是否达到最大月份12月
- time[4]=0x01; //重新回到01月
- Writeds1302 (WRITE_MONTH,time[4]); //将设置好的月份写入到DS1302存储起来
- }
-
- if(set_f==3) //设置日
- {
- time[3]++; //日份+1
- time[3]=(time[3]/10)*16+time[3]%10; //将日份转换成16进制,例如:15日-->0x15
- 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天
- {
- if(time[3]>0x31) //判断是否达到最大日份31日
- time[3]=0x01; //重新回到01日
- }
- else //否者2,4,6,9,11为小月
- {
- if(time[4]==0x02) //如果是2月,需要区分闰、平年
- {
- if(((!(time[6]%4) && (time[6]%100)) || !(time[6]%400))==0)//如果闰年
- {
- if(time[3]>0x28) //判断是否达到最大日份28日
- time[3]=0x01; //重新回到01日
- }
- else //否者平年
- {
- if(time[3]>0x29) //判断是否达到最大日份29日
- time[3]=0x01; //重新回到01日
- }
- }
- else //否者为剩下的月份
- {
- if(time[3]>0x30) //判断是否达到最大日份30日
- time[3]=0x01; //重新回到01日
- }
- }
- Writeds1302 (WRITE_DAY,time[3]); //将设置好的日份写入到DS1302存储起来
- }
-
- if(set_f==4) //设置时,同上
- {
- time[2]++;
- time[2]=(time[2]/10)*16+time[2]%10;
- if(time[2]>0x23)
- time[2]=0x00;
- Writeds1302 (WRITE_HOUR,time[2]);
- }
-
- if(set_f==5) //设置分,同上
- {
- time[1]++;
- time[1]=(time[1]/10)*16+time[1]%10;
- if(time[1]>0x59)
- time[1]=0x00;
- Writeds1302 (WRITE_MINUTE,time[1]);
- }
-
- if(set_f==6) //设置秒,同上
- {
- time[0]++;
- time[0]=(time[0]/10)*16+time[0]%10;
- if(time[0]>0x59)
- time[0]=0x00;
- Writeds1302 (WRITE_SECOND,time[0]);
- }
-
- if(set_f==7) //设置定时起始时间——时
- {
- if(ds[0]<23)
- ds[0]++;
- else
- ds[0]=0;
- }
-
- if(set_f==8) //设置定时起始时间——分
- {
- if(ds[1]<59)
- ds[1]++;
- else
- ds[1]=0;
- }
- if(set_f==9) //设置定时结束时间——时
- {
- if(ds[2]<23)
- ds[2]++;
- else
- ds[2]=0;
- }
-
- if(set_f==10) //设置定时结束时间——分
- {
- if(ds[3]<59)
- ds[3]++;
- else
- ds[3]=0;
- }
- if(set_f==11) //设置 光强上限值
- {
- if(light_up<99)//最大值可设置99%
- light_up++;//光强上限值+1%
- }
-
- if(set_f==12) //设置 光强下限值
- {
- if(light_down<99&&light_down+1<light_up)//最大值可设置99%,并且下限不能超过上限
- light_down++;//光强下限值+1%
- }
- }
- else
- if((hw_data=='+'||key_jia==0)&&set_f==0&&mode==0)//手动控制窗帘打开
- {
- if(moto_state==1&&moto_f==1)//已经在控制状态。并且控制打开
- moto_state=2; //停止运作
- else
- {
- if(moto_num<192)//判断是否不处于打开状态
- {
- moto_f=1; //控制开闭窗
- moto_state=1; //开启运作
- }
- }
- while(!key_jia); //等待按键松开
- }
- }
- //减键
- if(hw_data=='-'||key_jian==0)
- {
- delayms(7);
- if((hw_data=='-'||key_jian==0)&&set_f!=0)
- {
- if(set_f==1) //设置年
- {
- if(time[6]==0) //判断当前是否为00年
- time[6]=79; //如果是回到最大年份:79年
- else
- time[6]--; //否者,年份-1
- time[6]=(time[6]/10)*16+time[6]%10;//将年份转换成16进制,例如:16年-->0x16
- Writeds1302 (WRITE_YEA,time[6]); //将设置好的年份写入到DS1302存储起来
- }
-
- if(set_f==2) //设置月,同上
- {
- if(time[4]==1)
- time[4]=12;
- else
- time[4]--;
- time[4]=(time[4]/10)*16+time[4]%10;
- Writeds1302 (WRITE_MONTH,time[4]);
- }
-
- if(set_f==3) //设置日,同上
- {
- time[3]--;
- time[3]=(time[3]/10)*16+time[3]%10;
- if(time[4]==1||time[4]==3||time[4]==5||time[4]==7||time[4]==8||time[4]==10||time[4]==12)
- {
- if(time[3]<0x01)
- time[3]=0x31;
- }
- else
- {
- if(time[4]==0x02)
- {
- if(((!(time[6]%4) && (time[6]%100)) || !(time[6]%400))==0)
- {
- if(time[3]<0x01)
- time[3]=0x28;
- }
- else
- {
- if(time[3]<0x01)
- time[3]=0x29;
- }
- }
- else
- {
- if(time[3]<0x01)
- time[3]=0x30;
- }
- }
- Writeds1302 (WRITE_DAY,time[3]);
- }
-
- if(set_f==4) //设置时,同上
- {
- if(time[2]==0)
- time[2]=23;
- else
- time[2]--;
- time[2]=(time[2]/10)*16+time[2]%10;
- Writeds1302 (WRITE_HOUR,time[2]);
- }
-
- if(set_f==5) //设置分,同上
- {
- if(time[1]==0)
- time[1]=59;
- else
- time[1]--;
- time[1]=(time[1]/10)*16+time[1]%10;
- Writeds1302 (WRITE_MINUTE,time[1]);
- }
-
- if(set_f==6) //设置秒,同上
- {
- if(time[0]==0)
- time[0]=59;
- else
- time[0]--;
- time[0]=(time[0]/10)*16+time[0]%10;
- Writeds1302 (WRITE_SECOND,time[0]);
- }
- if(set_f==7) //设置定时起始时间——时
- {
- if(ds[0]>0)
- ds[0]--;
- else
- ds[0]=23;
- }
-
- if(set_f==8) //设置定时起始时间——分
- {
- if(ds[1]>0)
- ds[1]--;
- else
- ds[1]=59;
- }
- if(set_f==9) //设置定时结束时间——时
- {
- if(ds[2]>0)
- ds[2]--;
- else
- ds[2]=23;
- }
-
- if(set_f==10) //设置定时结束时间——分
- {
- if(ds[3]>0)
- ds[3]--;
- else
- ds[3]=59;
- }
- if(set_f==11) //设置 光强上限值
- {
- if(light_up!=0&&light_up>light_down+1)//最小值可设置成0,并且上限值要大于下限值
- light_up--; //光强上限值-1%
- }
-
- if(set_f==12) //设置 光强下限值
- {
- if(light_down!=0)//最小值可设置成0
- light_down--;//光强下限值-1%
- }
- }
- else
- if((hw_data=='-'||key_jian==0)&&set_f==0&&mode==0)//手动控制窗户关闭
- {
- if(moto_state==1&&moto_f==0)//已经在控制状态。并且控制打开
- moto_state=0; //停止运作
- else
- {
- if(moto_num>0)//判断是否不处于打开状态
- {
- moto_f=0; //控制开闭窗
- moto_state=1; //开启运作
- }
- }
- while(!key_jian); //等待按键松开
- }
- }
- //红外遥控切换模式
- if(hw_data=='|'&&set_f==0)
- {
- mode++; //模式变量+1
- if(mode>=3) //最大3个模式
- mode=0; //重新回到第1个模式
- if(moto_state==1) //如果处于运转过程中
- {
- if(moto_f==0) //控制步进电机关闭
- moto_state=0;
- else //控制步进电机打开
- moto_state=2;
- }
- EEPROM_delete(0x2400); //擦除扇区
- EEPROM_write(0x2400,mode); //写入【模式】数据保存
- }
- //红外遥控切换设置上一个参数
- if(hw_data=='<'&&set_f!=0)
- {
- if(set_f==7||set_f==11)
- {
- LCD_write_command(0x01); //清除屏幕显示
- delay_n40us(100); //延时等待全部清除完毕
- set_f=6;
- }
- else
- if(set_f==1)
- {
- LCD_write_command(0x01);//清除屏幕显示
- delay_n40us(100); //延时等待全部清除完毕
- switch(mode)//根据对应的模式,设置对应的参数
- {
- case 0: set_f=6; break; //手动模式
- case 1: set_f=10; break;//定时模式
- case 2: set_f=12; break;//光控模式
- default: break;
- }
- }
- else
- set_f--;
- }
- //红外遥控切换设置下一个参数
- if(hw_data=='>'&&set_f!=0)
- {
- if(set_f==6) //日期、时间校准完
- {
- LCD_write_command(0x01);//清除屏幕显示
- delay_n40us(100); //延时等待全部清除完毕
- set_f=13; //跳到校准窗帘状态
- }
- else
- if(set_f==10||set_f==12)
- {
- LCD_write_command(0x01); //清除屏幕显示
- delay_n40us(100); //延时等待全部清除完毕
- set_f=1; //进入校准时间
- }
- else
- set_f++; //设置变量+1
- if(set_f>12)
- {
- Writeds1302 (WRITE_PROTECT,0X00);//禁止DS1302写保护
- LCD_write_command(0x01); //清除屏幕显示
- delay_n40us(100); //延时等待全部清除完毕
- switch(mode)//根据对应的模式,设置对应的参数
- {
- case 0: set_f=1; break; //手动模式
- case 1: set_f=7; break; //定时模式
- case 2: set_f=11; break; //光控模式
- default: break;
- }
- }
- }
- hw_data=0xff;//清除红外接收的数据
- }
- /********************************************************
- 函数名称:void mian()
- 函数作用:主函数
- 参数说明:
- ********************************************************/
- void main()
- {
- uchar lowtime; //记录上次采集光强的时间
- uchar nums; //循环计数变量
- if(key_ok==0)
- {
- delayms(100);
- if(key_ok==0)
- {
- EEPROM_delete(0x2200); //擦除扇区
- EEPROM_write(0x2200,8); //写入【定时时间】数据保存
- EEPROM_write(0x2210,30);//写入【定时时间】数据保存存
- EEPROM_write(0x2220,16);//写入【定时时间】数据保存存
- EEPROM_write(0x2230,20);//写入【定时时间】数据保存存
- EEPROM_write(0x2240,80);//写入【光强上限值】数据保存
- EEPROM_write(0x2250,30);//写入【光强下限值】数据保存
- EEPROM_delete(0x2400); //擦除扇区
- EEPROM_write(0x2400,0); //写入【模式】数据保存
- }
- }
- ds[0]=EEPROM_read(0x2200); //读取存储的【定时时间】数据
- ds[1]=EEPROM_read(0x2210); //读取存储的【定时时间】数据
- ds[2]=EEPROM_read(0x2220); //读取存储的【定时时间】数据
- ds[3]=EEPROM_read(0x2230); //读取存储的【定时时间】数据
- light_up=EEPROM_read(0x2240); //读取存储的【光强上限值】数据
- light_down=EEPROM_read(0x2250); //读取存储的【光强下限值】数据
- mode=EEPROM_read(0x2400); //读取存储的【模式】数据
- HW_init(); //红外接收初始化
- LCD_init(); //LCD1602初始化
- ADC0832_read(0);
- ADC0832_read(0);
- while(1) //死循环
- {
- scan(); //按键检测处理
- if(set_f==0) //正常显示
- {
- nums++; //循环次数+1
- if(nums==10) //每循环10次,读取一次日期、时间
- {
- nums=0; //重置循环次数
- Read_time(); //读取日期、时间
- }
- if(time[0]!=lowtime) //时间过去一秒
- {
- lowtime=time[0]; //重新记录时间
- light=ADC0832_read(0);//读取AD值
- light=light*100/255;//转换为光强
- }
- display(); //更新显示数据
- }
- else
- if(set_f<7) //校准日期、时间
- {
- Read_time(); //读取日期、时间
- display2();
- }
- else
- if(set_f<11) //设置定时
- display3();
- else
- if(set_f<13) //设置光强控制值
- display4();
- }
- }
复制代码
所有资料51hei提供下载:
51智能窗帘.7z
(4.32 MB, 下载次数: 173)
|