功能描述
1、采用51/52单片机作为主控芯片;
2、采用1602液晶显示:当前日期和时间、控制模式、光照强度;
3、采用DS1302时钟芯片,日期时间可调;
4、共3种模式:手动模式(Manual)、光控模式(Liging)、定时模式(Timing);
5、在手动模式下,通过按键进行开关控制,亦可通过红外遥控器控制;
6、在光控模式下,光照强度大于设置值时开窗,否则关闭;
7、在定时模式下,通过按键设置开窗帘和关窗帘的时间;
8、电机正转半圈,模拟开窗,红色LED灯点亮;
9、电机反转半圈,模拟关窗,红色LED灯熄灭。
电路设计
采用Altium Designer作为电路设计工具。Altium Designer通过把原理图设计、PCB绘制编辑、拓扑逻辑自动布线、信号完整性分析和设计输出等技术的完美融合,为设计者提供了全新的设计解决方案,使设计者可以轻松进行设计,熟练使用这一软件必将使电路设计的质量和效率大大提高。
单片机管脚说明:
P0端口(P0.0-P0.7):P0口为一个8位漏极开路双向I/O口,每个引脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1端口(P1.0-P1.7):P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高电平,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。
P2端口(P2.0-P2.7):P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口,用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
P3端口(P3.0-P3.7):P3口管脚是一个带有内部上拉电阻的8位的双向I/O端口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入端时,由于外部下拉为低电平,P3口将输出电流(ILL)。P3口同时为闪烁编程和编程校验接收一些控制信号。
仿真设计
采用Proteus作为仿真设计工具。Proteus是一款著名的EDA工具(仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一键切换到PCB设计,真正实现了从概念到产品的完整设计。
主程序设计
void main()
{
uchar light;
LcdInit(); // 执行液晶初始化
DS1302_Init(); // 时钟芯片的初始化
LcdShowInit(); // 液晶显示内容的初始化
io_inithw();
int_inithw();
if(DS1302_Read_Byte(0x81)>=128) // 判断时钟芯片是否正在运行
{
DS1302_Write_Time(); // 如果没有,则初始化一个时间
}
while(1)
{
DS1302_Read_Time(); // 获取当前时钟芯片的时间,存在数组time_buf中
FlashTime(); // 刷新时间显示
light=Get_ADC0832(); // 读取光照强度
light=light/2.5; // 缩小光照检测结果(在0-99)
if(light>99) // 如果大于99
light=99; // 则依然保持99
LcdGotoXY(1,14); // 光标定位
LcdPrintNum(light); // 显示光照强度
KeyScanf1(); // 按键扫描(时间的设置)
KeyScanf2(); // 按键扫描(阈值的设置)
KeyScanf3(); // 按键扫描(模式切换)
/*手动控制模式*/
if(gMode==1)
{
if(closeflag==1)
{
if(Led_P==0) // 如果窗帘当前是打开的
{
closeflag=0;
Close(); // 则光标窗帘
}else
closeflag=0;
}
if(KeyDown_P==0) // 如果关窗帘键按下了
{
if(Led_P==0) // 如果窗帘当前是打开的
{
Close(); // 则光标窗帘
}
}
if(openflag==1)
{
if(Led_P==1) // 如果窗帘当前是关闭的
{
openflag=0;
Open(); // 则打开窗帘
}else{
openflag=0;
}
}
if(KeyUp_P==0) // 如果开窗帘键按下了
{
if(Led_P==1) // 如果窗帘当前是关闭的
{
Open(); // 则打开窗帘
}
}
}
/*时间控制模式*/
if(gMode==2)
{
if((TimeBuff[4]==CloseHour)&&(TimeBuff[5]==CloseMinute)&&(TimeBuff[6]==0)) // 如果到了关窗帘的时间
{
if(Led_P==0) // 如果窗帘当前是打开的
{
Close(); // 则光标窗帘
}
}
if((TimeBuff[4]==OpenHour)&&(TimeBuff[5]==OpenMinute)&&(TimeBuff[6]==0)) // 如果到了开窗帘的时间
{
if(Led_P==1) // 如果窗帘当前是关闭的
{
Open(); // 则打开窗帘
}
}
}
/*光线控制模式*/
if(gMode==3)
{
if(light<gLight) // 当前光线小于设置的阈值
{
if(Led_P==0) // 如果窗帘当前是打开的
{
Close(); // 则光标窗帘
}
}
else // 当前光线大于或等于设置的阈值
{
if(Led_P==1) // 如果窗帘当前是关闭的
{
Open(); // 则打开窗帘
}
}
}
DelayMs(100); // 延时0.1秒
}
}
void interrupt0()interrupt 0
{
uchar i=0,j=0,k=0,us=0;
uchar addr[4]={0};
int aa=0x00;
EX0=0;
for(i=0;i<255;i++) //9ms内有高电平认为是干扰
{
if(P3&0x04) //255的值实际时间为800us
{
EX0=1;
return;
}
}
while(!(P3&0x04)); //等待9ms低电平过去
for(i=0;i<4;i++)
{
for(j=0;j<8;j++)
{
while(P3&0x04); //等待4.5ms高电平过去
while(!(P3&0x04)); //等待0.56ms低电平后面的高电平
while(P3&0x04) //计算这个高电平的时间
{
for(us=0;us<=32;us++); //100us的延时语句
if((k++)>=30) //高电平时间过长退出程序
{
EX0=1;
return;
}
}
if(k>=8)
addr[i]=addr[i]|0x80; //高电平大于0.56ms,则为1
k=0;
}
}
aa=addr[2]; //P2的LED显示二进制键值
if(aa==0x07){
if(gMode==1)
{
openflag=1;
}
// Close();
}
if(aa==0x09){
if(gMode==1)
{
closeflag=1;
}
// Open();
}
EX0=1;
aa=0x00;
}
源文件获取
关注公众号-电子开发圈,首页发送 “智能窗” 获取;