系统总体方案
(附文件)
通过上述对各个模块介绍,我们最终选择了采用STC89C52作为的主控芯片,采用光敏电阻采集环境光强通过ADC0832转换成数字信息然后由单片机处理得出环境光强的情况,DS1302时钟芯片获取当前的时间信息,系统采用LCD1602实时显示光强、时间、日期和模式。通过四个独立按键可以进行切换模式模式、设置时间日期、设置光强限值、定时时间等并且系统还配备了红外遥控的功能。同时具有两个限位开关防止窗帘电机过度转动而造成窗帘损坏。
本设计的具体的系统方案如下图2.1所示。
框图:
原理图:
DS1302的工作原理
在使用时候由于DS1302的数据引脚是双向通讯的,而51单片机引脚属于弱上拉如果不添加10K的上拉电阻会导致弱上拉时端口的电平翻转而通讯不成功,而RST和SCLK是单向的不外加上拉也可以,添加也可以。在本设计中将这三个端口都添加了10K上拉电阻。具体的电路图如图3.10所示。
ADC0832的工作原理
步进电机原理构造
步进电机是一种将电脉冲转化为角位移的执行机构。通俗的说:也就是当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(即步进角)。可以通过控制脉冲的个数来控制角位移量,从而达到准确定位的目的;同时可以通过控制脉冲的频率来控制电机转动的速度和加速度,从而做到调速的目的。
步进电机28BYJ48型四相八拍电机,工作电压为:DC5V-DC12V。当对步进电机施加一系列连续不断地控制脉冲时,它可以连续不断转动。每一个脉冲信号对应步进电机的某一相或两相绕组的通电状态改变一次,也就对应转子转过一定的角度(一个步距角)。当通电状态的改变完成一个循环时,转子转过一个齿距。四相步进电机可以在不同的通电方式下运行,常见的通电方式有单四拍(单相绕组通电):A-B-C-D-A….,双四拍(双相绕组通电):AB-BC-CD-DA-AB…;八拍:A-AB-B-BC-C-CD-D-DA-A…。
ULN2003与单片机的连接
本设计中采用ULN2003驱动步进电机,设计中将单片机的P1.0P1.3引脚分别接到ULN2003的R1R4上,输出端Q1~Q4接到28BYJ-48步进电机的蓝、粉、黄、橙四根线上也就是ABCD四相上。如图3.14所示。
HX1838红外一体接收头的介绍
一体化红外接收头指的是红外接收相关电路被集成在一个元件中。HX1838就是这样一个集成的一体化红外接收头,内部集成了红外监测二极管、放大器、积分电路、限幅器、比较器、带通滤波器等电路。当红外监测二极管监测到红外信号,然后将信号传送到放大器和限幅器,限幅器将脉冲幅度控制在一定范围,而不管红外发射装置和接收头的距离远近。交流信号进入带通滤波器,带通滤波器可以通过30khz到60khz的负载波,通过解调电路和积分电路进入比较器,比较器输出高低电平,还原出发射装置的信号波形
HX1838连接到单片机的P3.2外部中断输入引脚上,这样有接收到红外信号就可以第一时间响应进入解码阶段。而51单片机引脚属于弱上拉如果不添加10K的上拉电阻会导致弱上拉时端口的电平翻转而通讯不成功,所以在HX1838信号引脚上添加一个10K的上拉电阻。HX1838与单片机连接电路图如图3.16所示。
系统软件部分设计
部分代码:
/*************************************************************
智能窗帘
补充说明:
***************************************************************/
#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 ");
}
}
.
链接:https://pan.baidu.com/s/1GT7r8yXGJEkR4KJ6jDY0EQ
提取码:cj8a
.