电动窗帘主要有以下几大功能:(1)手动控制:该功能使电动窗帘具有手动正传、手动反转 和手动停止的功能。而且增加了工作状态指示,电机工作在正传、反转和停止状态的时候,手机APP上均有不同工作状态指示。(2)自动控制:窗帘的关闭和开启通过环境亮度自动完成窗帘的开启或关闭操作,“天黑关闭,天亮打开”具有智能管理,不产生误动作。(3)防过卷功能:通过在窗户两边各安装一个行程开关,当窗帘开启或关闭到位时,行程开关动作,然后单片机发出控制信号使步进电机停止动作。
窗帘的正转、反转和停止功能可由手机APP通过蓝牙通讯向单片机发布命令来控制步进电机的运转以实现。自动控制通过光线检测电路来控制单片机输出电平继而控制电机的正转和反转。
软件程序代码:
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
#include"XPT2046.h"
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
u8 receiveData;
sbit led=P2^4; //手动运行指示灯
sbit xcg=P3^2; //左行程开关
sbit xck=P3^3; //右行程开关
u8 tab[]={0x0e,0x0c,0x0d,0x09,0x0b,0x03,0x07,0x06};
u8 a=0,b=1;//用于记忆行程开关状态
void delay(u16 i)//延时函数
{
while(i--);
}
void UsartConfiguration()
{
SCON=0X50; //设置为工作方式1
TMOD=0X20; //设置定时器1工作方式2
TH1=0XFD; //定时器装初值(波特率为9600)
TL1=0XFD;
ES=1; //开串行中断
EA=1; //开总中断
TR1=1; //启动定时器1
}
void motor1()//关窗帘
{
u8 i;
for(i=0;i<8;i++)
{
P1=tab;
delay(180);
}
}
void motor2()//开窗帘
{
u8 i;
for(i=7;i>=0;i--)
{
P1=tab;
delay(180);
}
}
void xcg1()
{
if(xcg==0) //检测按键是否按下
{
delay(600); //消除抖动 一般大约10ms
if(xcg==0) //再次判断按键是否按下
{
a=0;
b=1;
}
}
}
void xck1()
{
if(xck==0) //检测按键是否按下
{
delay(600); //消除抖动 一般大约10ms
if(xck==0) //再次判断按键是否按下
{
a=1;
b=0;
}
}
}
void main()
{
u16 light,mode=1;//开机进入自动模式(mode=1)
UsartConfiguration();
while(1)
{
while(mode==1)//自动模式
{
led=1;
light=Read_AD_Data(0xA4);//读取光敏电阻值
if(receiveData=='S'){mode=0;}//手动模式
while (a==1&&light<150)//关窗帘
{
if(receiveData=='S'){mode=0;light=150;}
while(receiveData=='T'){P1=0xFF;}
motor1();
xcg1();
}
while (b==1&&light>200)//开窗帘
{
if(receiveData=='S'){mode=0;light=200;}
while(receiveData=='T'){P1=0xFF;}
motor2();
xck1();
}
P1=0xFF;//电机断电停止
}
while(mode==0)//手动模式
{ led=0;//手动控制指示灯
if (receiveData=='Z'){mode=1;}
while (a==1&&receiveData=='G')//关窗帘
{
motor1();
b=1;
xcg1();
while(receiveData=='T'){P1=0xFF;}
}
while (b==1&&receiveData=='K')//开窗帘
{
motor2();
a=1;
xck1();
while(receiveData=='T'){P1=0xFF;}
}
P1=0xFF;
}
}
}
void Usart() interrupt 4 //串行口中断
{
receiveData=SBUF; //接收数据
RI = 0; //清除接收中断标志位
}
AD转换 XPT2046.h程序:
#include"XPT2046.h"
sbit DOUT = P3^7; //输出
sbit CLK = P3^6; //时钟
sbit DIN = P3^4; //输入
sbit CS = P3^5; //片选
uint Read_AD_Data(uchar cmd);
uint SPI_Read(void);
void SPI_Write(uchar dat);
void SPI_Start(void)
{
CLK = 0;
CS = 1;
DIN = 1;
CLK = 1;
CS = 0;
}
void SPI_Write(uchar dat)
{
uchar i;
CLK = 0;
for(i=0; i<8; i++)
{
DIN = dat >> 7; //放置最高位
dat <<= 1;
CLK = 0; //上升沿放置数据
CLK = 1;
}
}
uint SPI_Read(void)
{
uint i, dat=0;
CLK = 0;
for(i=0; i<12; i++) //接收12位数据
{
dat <<= 1;
CLK = 1;
CLK = 0;
dat |= DOUT;
}
return dat;
}
uint Read_AD_Data(uchar cmd)
{
uchar i;
uint AD_Value;
CLK = 0;
CS = 0;
SPI_Write(cmd);
for(i=6; i>0; i--); //延时等待转换结果
CLK = 1; //发送一个时钟周期,清除BUSY
_nop_();
_nop_();
CLK = 0;
_nop_();
_nop_();
AD_Value=SPI_Read();
CS = 1;
return AD_Value;
}
|