单片机源程序如下:
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char // 以后unsigned char就可以用uchar代替
#define uint unsigned int // 以后unsigned int 就可以用uint 代替
sbit ADC_CS = P1^6; // ADC0832的CS引脚
sbit ADC_CLK = P1^7; // ADC0832的CLK引脚
sbit ADC_DAT = P3^2; // ADC0832的DI/DO引脚
sbit KeyMode_P = P3^3; // 模式切换
sbit KeyDown_P = P3^6; // 减按键
sbit KeyUp_P = P3^7; // 加按键
sbit Led_P = P2^0; // 指示灯
uchar gLight = 40; // 窗帘开关的阈值
uchar gMode=1; // 1是手动模式,2是亮度自动模式
uchar code Clock[]={0x80,0x40,0x20,0x10}; // 步进电机顺时针旋转数组
uchar code AntiClock[]={0x10,0x20,0x40,0x80}; // 步进电机逆时针旋转数组
/*********************************************************/
// 毫秒级的延时函数,time是要延时的毫秒数
/*********************************************************/
void DelayMs(uint time)
{
uint i,j;
for(i=0;i<time;i++)
for(j=0;j<112;j++);
}
void KeyScanf3()
{
if(KeyMode_P==0)
{
gMode++; // 切换到下一模式
if(gMode==3) // 如果到尽头了
gMode=1; // 回到第一种模式
DelayMs(10); // 去除按键按下的抖动
while(!KeyMode_P); // 等待按键是否
DelayMs(10); // 去除按键松开的抖动
}
}
/*********************************************************/
// ADC0832的时钟脉冲
/*********************************************************/
void WavePlus()
{
_nop_();
ADC_CLK = 1;
_nop_();
ADC_CLK = 0;
}
/*********************************************************/
// 获取指定通道的A/D转换结果
/*********************************************************/
uchar Get_ADC0832()
{
uchar i;
uchar dat1=0;
uchar dat2=0;
ADC_CLK = 0; // 电平初始化
ADC_DAT = 1;
_nop_();
ADC_CS = 0;
WavePlus(); // 起始信号
ADC_DAT = 1;
WavePlus(); // 通道选择的第一位
ADC_DAT = 0;
WavePlus(); // 通道选择的第二位
ADC_DAT = 1;
for(i=0;i<8;i++) // 第一次读取
{
dat1<<=1;
WavePlus();
if(ADC_DAT)
dat1=dat1|0x01;
else
dat1=dat1|0x00;
}
for(i=0;i<8;i++) // 第二次读取
{
dat2>>= 1;
if(ADC_DAT)
dat2=dat2|0x80;
else
dat2=dat2|0x00;
WavePlus();
}
_nop_(); // 结束此次传输
ADC_DAT = 1;
ADC_CLK = 1;
ADC_CS = 1;
if(dat1==dat2) // 返回采集结果
return dat1;
else
return 0;
}
/*********************************************************/
// 开窗
/*********************************************************/
void Open()
{
uint i,j;
for(j=0;j<255;j++) // 控制步进电机正转
{
for(i=0;i<4;i++)
{
P2=Clock[ i];
DelayMs(3);
}
}
Led_P=0;
}
/*********************************************************/
// 关窗
/*********************************************************/
void Close()
{
uint i,j;
for(j=0;j<255;j++) // 控制步进电机反转
{
for(i=0;i<4;i++)
{
P2=AntiClock[ i];
DelayMs(3);
}
}
Led_P=1;
}
/*********************************************************/
// 主函数
/*********************************************************/
void main()
{
uchar light;
while(1)
{
light=Get_ADC0832();
light=light/2.5; // 缩小光照检测结果(在0-99)
if(light>99) // 如果大于99
light=99; // 则依然保持99
KeyScanf3(); // 按键扫描(模式切换)
/*手动控制模式*/
if(gMode==1)
{
if(KeyDown_P==0) // 如果关窗帘键按下了
{
if(Led_P==0) // 如果窗帘当前是打开的
{
Close(); // 则关闭窗帘
}
}
if(KeyUp_P==0) // 如果开窗帘键按下了
{
if(Led_P==1) // 如果窗帘当前是关闭的
{
Open(); // 则打开窗帘
}
}
}
/*光线控制模式*/
if(gMode==2)
{
if(light<gLight) // 当前光线小于设置的阈值
{
if(Led_P==0) // 如果窗帘当前是打开的
{
Close(); // 则关闭窗帘
}
}
else // 当前光线大于或等于设置的阈值
{
if(Led_P==1) // 如果窗帘当前是关闭的
{
Open(); // 则打开窗帘
}
}
}
DelayMs(100); // 延时0.1秒
}
} |