//宏定义
#define uint unsigned int
#define uchar unsigned char
#define DUAN P0
//头函数
#include <reg52.h>
uchar code ssw[]=
{
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90
};
uchar code wei[]=
{
0xfe,0xfd,0xfb,0xf7
};
uchar pdata tt[51]; //定义空数组用于AD0809取平均值
uchar scale=20,rsd_sec,put[4]; //定义占空比比例,热释电计时秒变量
char min,sec; //定义计时分秒
bit bdata flag_auto,ss,flag_bs,flag_rsd,flag_jiejin=1; //位定义自动切换的,闪烁标志,报警位标志,热释电动作标志,接近传感器标志
uchar flag_set=0,time; //设置变量:0 正常 1 调分 2 调秒
uint lum;
bit beep1; //ad0809读出值
//函数声明
void delay(uchar i);
//管脚声明
sbit LED = P3^5; //灯光控制输出
sbit change= P1^4; //自动模式切换按键
sbit set = P1^5; //设置按键
sbit add = P1^6; //加按键
sbit sub = P1^7; //减按键
sbit rsd = P3^6; //热释电
sbit jiejin=P3^4; //接近开关
sbit buzz=P3^7;
sbit led_1=P3^2;
sbit led_2=P3^3;
sbit CS=P1^2;
sbit CLK=P1^0;
sbit DIO=P1^1;
void display()
{
uchar i;
if(flag_set==1&&ss==0)
{
put[0]=0xff;
put[1]=0xff&0x7f;
}else
{
put[0]=ssw[min/10%10];
put[1]=ssw[min%10]&0x7f;
}
if(flag_set==2&&ss==0)
{
put[2]=0xff;
put[3]=0xff;
}else
{
put[2]=ssw[sec/10%10];
put[3]=ssw[sec%10];
}
for(i=0;i<4;i++)
{
P2=wei[i];
P0=put[i];
delay(1);
P0=0xff;
}
}
unsigned int A_D()
{
unsigned char i,dat;
CS=1; //一个转换周期开始
CLK=0; //为第一个脉冲作准备
CS=0; //CS置0,片选有效
DIO=1; //DIO置1,规定的起始信号
CLK=1; //第一个脉冲
CLK=0; //第一个脉冲的下降沿,此前DIO必须是高电平
DIO=1; //DIO置1, 通道选择信号
CLK=1; //第二个脉冲,第2、3个脉冲下沉之前,DI必须跟别输入两位数据用于选择通道,这里选通道CH0
CLK=0; //第二个脉冲下降沿
DIO=0; //DI置0,选择通道0
CLK=1; //第三个脉冲
CLK=0; //第三个脉冲下降沿
DIO=1; //第三个脉冲下沉之后,输入端DIO失去作用,应置1
CLK=1; //第四个脉冲
for(i=0;i<8;i++) //高位在前
{
CLK=1; //第四个脉冲
CLK=0;
dat<<=1; //将下面储存的低位数据向右移
dat|=(unsigned char)DIO; //将输出数据DIO通过或运算储存在dat最低位
}
CS=1; //片选无效
return dat; //将读出的数据返回
}
/*****************按键函数*****************/
void KEY()
{
uint lum_mean,lum_all;
uchar b,c;
if(change==0) //自动切换按键按下
{
delay(10); //去抖
if(change==0) //再次判断按键按下
{
buzz=0; //蜂鸣器鸣响
flag_auto=!flag_auto; //自动模式标志位取反
if(flag_auto==1) //当切换到手动模式时 首先将LED发光比例设置在50%
scale=20;
if(flag_auto==0)
{
led_1=0;
led_2=1;
}else
{
led_1=1;
led_2=0;
}
}
while(!change) display();buzz=1; //按键释放 松开按键后关闭蜂鸣器
}
if(jiejin==0&&flag_jiejin==1) //接近传感器检测到障碍时 开启报警
{
buzz=0;
flag_jiejin=0;
}
if(jiejin!=flag_jiejin) //接近传感器检测不到障碍时 关闭报警
{
buzz=1;
flag_jiejin=1;
}
if(set==0) //设置键按下时
{
delay(10);
if(set==0)
{
buzz=0;
flag_set++; //设置变量++
if(flag_set==3) //加到3时回复回正常模式
flag_set=0;
flag_bs=0; //按下设置 关闭报警
}
while(!set) display(); buzz=1; //按键释放
}
if(flag_set==1) //加键按键只有在设置状态(flag_set!=0)时按下才有效
{ //调分时
if(add==0) //加按键按下时
{
delay(10);
if(add==0)
{
buzz=0;
min++; //分++
if(min>=60)
min=0;
}
while(!add) display(); buzz=1;
}
if(sub==0) //减按键按下时
{
delay(10);
if(sub==0)
{
buzz=0;
min--; //分--
if(min<0)
min=59;
}
while(!sub) display(); buzz=1;
}
}
if(flag_set==2)
{ //调秒时
if(add==0) //加键按下
{
delay(10);
if(add==0)
{
buzz=0;
sec++; //秒++
if(sec>=60)
sec=0;
}
while(!add) display(); buzz=1;
}
if(sub==0) //减键按下
{
delay(10);
if(sub==0)
{
buzz=0;
sec--; //秒--
if(sec<0)
sec=59;
}
while(!sub) display(); buzz=1;
}
while(!sub);
}
if(flag_auto==0) //自动模式时
{
if(flag_rsd==1) //且有人在范围内时
{
for(b=0;b<49;b++) //将空数组tt【】内数值整体左移一位
{
tt[b]=tt[b+1]; //将后一数值放到前一位置
}
tt[49]=A_D(); //将读出的ad0809数值放入tt【49】
for(c=0;c<50;c++) //将tt【】内数值相加
{
lum_all=lum_all+tt[c];
}
lum_mean=lum_all/50; //将总数/50取出平均值
lum_all=0; //将总数清零
if(lum_mean<=130) scale=1; //判断取出平均值大小 小于30 发光强度0%
else if(lum_mean>=254) scale=41; //大于150 发光强度100%
else scale=((lum_mean-130)/3)+1; //其他值时将其计算得到发光强度 (计算目的是为了得到一个1-41之间的数值 控制灯光变化)
}
else
scale=1; //没有人在范围内时 将灯光亮度调至0%
}
else //手动模式下
{
if(flag_set==0) //正常模式下
{
if(add==0) //加键按下
{
delay(10);
if(add==0)
{
// buzz=0;
scale++; //灯光比例++
if(scale>=41)
scale=41;
display();
}
// while(!add) display(); buzz=1;
}
if(sub==0) //减键按下时
{
delay(10);
if(sub==0)
{
// buzz=0;
scale--; //灯光比例--
if(scale<=1)
scale=1;
display();
}
// while(!sub) display(); buzz=1;
}
}
}
}
/*********定时器初始化函数**********/
void init()
{
TMOD=0x11; //工作方式
TH1=0x3c;
TL1=0xb0; //T1赋初值50ms
TH0=0xff;
TL0=0xe7; //T0赋初值25us
ET0=1;
ET1=1; //打开中断允许开关
EA=1; //中断总开关
TR0=1;
TR1=1; //定时器定时开关
}
/****************主函数**********************/
void main()
{
init(); //调用初始化函数
flag_auto=1; //初始化手动模式
delay(500); //延时500ms后开机
led_1=1;
led_2=0;
while(1) //循环
{
KEY(); //调用按键函数
display(); //调用显示函数
}
}
/*****************延时函数:大约1ms************************/
void delay(uchar i)
{
uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
/******************定时器T0服务函数:脉冲发生函数*******************/
void time0() interrupt 1
{
uchar n;
TH0=0xff;
TL0=0xe7; //重新赋初值
n++; //每25us n++
if(n<scale) //n<设置比例时,打开灯
{
LED=1;
}
else if(n>=scale)//n大于等于设置比例时 关闭灯
{
LED=0;
}
if(n==40) //n==40 :25us*40=1ms 1kHZ
{
n=0; //n=0
}
else ;
}
/********************定时器T0服务函数:计时和闪烁控制********************/
void time1() interrupt 3
{
uchar m;
uchar flag_BJ=0;
TH1=0x3c;
TL1=0xb0; //重新赋初值
m++; //50ms m++
if((m==10||m==20)&&flag_set!=0) //每过500ms 并且 在设置状态时
{
ss=!ss; //闪烁变量取反
}
if(m%10==0&&time!=0)
{
time--;
buzz=!buzz;
}
if(m==20) //到达1s时
{
m=0; //m=0
if(rsd==0) //热释电无信号时
rsd_sec++; //热释电计时秒++
if(rsd_sec<=30&&rsd==1) //热释电计时秒小于等于30 并且 热释电有信号时
{
rsd_sec=0; //将热释电秒清零
flag_rsd=1; //标志位置1 控制AD0809采集数值 调节灯光亮度
}
else if(rsd_sec>30&&rsd==0) //热释电计时秒大于30 并且 热释电无信号时
{
flag_rsd=0; //标志位置0 停止ad0809转换 关闭灯光
rsd_sec=0; //热释电计时秒清零
}
/* if(flag_BJ==1)
{
buzz=1;
flag_BJ=0;
} */
if(flag_set==0&&flag_bs==0&&((min+sec)!=0)) //正常模式下&&未报警&&定时时间不为零时
{
sec--;
if(sec<0) //定时秒-- 小于0时
{
sec=59; //复位到59秒
min--; //分--
}
if(min<=0&&sec==0) //分和秒都减到零时
{
min=0;
flag_bs=1;
//flag_BJ=1;
//buzz=0; //蜂鸣器报警提示�