基于51单片机的智能台灯
(程序+PCB+原理图+设计报告)
功能介绍
具体功能:
1.光敏电阻感应光亮,将信息处理给单片机,根据环境亮度调节亮度;
2.使用E18- D80NK红外接近传感器,靠的太近,蜂鸣器会提醒报警;
3.使用HC-SR501人体红外传感器,光亮不够且检测到人体时台灯自动亮;
4.LED驱动电路采用3路串联、每路4颗的LED灯,可手动调节台灯亮度;
5.可以设定学习时间;
6.检测无人时(30秒)台灯自动熄灭 ,时间可调;
/*************************************************
* 名称 : 智能调光台灯
* 功能 : (1)亮度不够且有人靠近时台灯自动亮;
(2)靠的太近会提醒坐姿不正(蜂鸣器)
(3)附近无人时台灯自动熄灭(30秒) 时间可调
(4)根据环境亮度调节等亮度
(5)可手动调节台灯亮度
(6)设定学习时间
***********************************************************************/
//头函数
#include <reg52.h>
#include <ADC0809.H>
//宏定义
#define uint unsigned int
#define uchar unsigned char
#define DUAN P0 //数码管段位
unsigned char code tab[]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xba,0x20,0x28,0xff}; //0-9的显示码表 gc.debfa
unsigned char code tab_dian[]={0x80,0x9b,0x42,0x0a,0x19,0x0c,0x04,0x9a,0x00,0x08,0xdf}; //带点0-9的显示码表
uchar pdata tt[51]; //定义空数组用于AD0809取平均值
uchar scale=20,rsd_sec; //定义占空比比例,热释电计时秒变量
char min,sec; //定义计时分秒
//位定义
bit bdata flag_auto, //自动切换标志位
ss, //闪烁标志位
flag_bs, //报警位标志位
flag_rsd, //热释电动作标志位
flag_jiejin=1; //接近传感器标志位
uchar flag_set=0; //设置变量:0 正常 1 调分 2 调秒
uchar lum; //ad0809读出值
//函数声明
void delay(uchar i);
//管脚声明
sbit LED = P3^4; //PWM输出
sbit change= P2^3; //自动模式切换按键
sbit set = P2^2; //设置按键
sbit add = P2^1; //加按键
sbit sub = P2^0; //减按键
sbit rsd = P3^6; //热释电
sbit jiejin=P3^5; //接近开关
sbit buzz=P3^7;
sbit W0=P2^7; //数码管位端
sbit W1=P2^6;
sbit W2=P2^5;
sbit W3=P2^4;
/**********************************************************************
* 名称 : display();
* 功能 : 数码管显示
* 输入 : 无
* 输出 : 无
***********************************************************************/
void display()
{
if(flag_set==0) //正常模式下
{
DUAN=tab[min/10]; //送入段码,秒数高位
W0=0; //打开位地址
delay(1); //小延时
W0=1; //关闭位地址
DUAN=tab_dian[min%10]; //送入段码,秒数低位
W1=0;
delay(1);
W1=1;
DUAN=tab[sec/10]; //送入段码,分钟数高位
W2=0;
delay(1);
W2=1;
DUAN=tab[sec%10]; //送入段码,分钟数高位
W3=0;
delay(1);
W3=1;
}
else if(flag_set==1) //设置模式下闪烁相应位
{
if(ss==1) //闪烁标志 ss=1 正常显示
{
DUAN=~tab[min/10];
W0=0;
delay(1);
W0=1;
DUAN=~tab_dian[min%10];
W1=0;
delay(1);
W1=1;
}
else //闪烁标志 ss=0 熄灭相应位 达到闪烁效果 ss在定时器里500ms取反一次
{
DUAN=~tab[10]; //
W0=0;
delay(1);
W0=1;
DUAN=~tab_dian[10];
W1=0;
delay(1);
W1=1;
}
DUAN=~tab[sec/10];
W2=0;
delay(1);
W2=1;
DUAN=~tab[sec%10];
W3=0;
delay(1);
W3=1;
}
else
{
DUAN=~tab[min/10];
W0=0;
delay(1);
W0=1;
DUAN=~tab_dian[min%10];
W1=0;
delay(1);
W1=1;
if(ss==1)
{
DUAN=~tab[sec/10];
W2=0;
delay(1);
W2=1;
DUAN=~tab[sec%10];
W3=0;
delay(1);
W3=1;
}
else
{
DUAN=~tab[10];
W2=0;
delay(1);
W2=1;
DUAN=~tab[10];
W3=0;
delay(1);
W3=1;
}
}
}
/**********************************************************************
* 名称 : KEY();
* 功能 : 按键控制
* 输入 : 无
* 输出 : 无
***********************************************************************/
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发光比例PWM设置在50%
scale=20;
}
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]=ADC0809(); //将读出的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<=30) scale=1; //判断取出平均值大小 小于30 发光强度0%
else if(lum_mean>=150) scale=41; //大于150 发光强度100%
else scale=((lum_mean-30)/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;
}
}
}
}
/**********************************************************************
* 名称 : init();
* 功能 : 初始化定时器
* 输入 : 无
* 输出 : 无
***********************************************************************/
void init()
{
TMOD=0x11; //工作方式1
TH1=0x3c;
TL1=0xb0; //T1赋初值50ms
TH0=0xff;
TL0=0xe7; //T0赋初值25us
ET0=1;
ET1=1; //打开中断允许开关
EA=1; //中断总开关
TR0=1; //开定时器0 开关
TR1=0; //关定时器0 开关
}
/**********************************************************************
* 名称 : main();
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void main()
{
init(); //调用初始化函数
flag_auto=1; //初始化手动模式
rsd=0; //热释电引脚置低(有信号时时高电平)
delay(500); //延时500ms后开机
while(1) //大循环
{
KEY(); //调用按键函数
display(); //调用显示函数
}
}
/**********************************************************************
* 名称 : delay();
* 功能 : 延时函数:大约1ms
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay(uchar i)
{
uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
/**********************************************************************
* 名称 : void time0() interrupt 1
* 功能 : 定时器T0 中断服务函数:PWM脉冲发生函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
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 ;
}
/**********************************************************************
* 名称 : void time1() interrupt 3
* 功能 : 定时器T1 中断服务函数:计时和闪烁控制 红外热释
* 输入 : 无
* 输出 : 无
***********************************************************************/
void time1() interrupt 3
{
uchar m;
TH1=0x3c;
TL1=0xb0; //重新赋初值
m++; //50ms m++
if((m==10||m==20)&&flag_set!=0) //每过500ms 并且 在设置状态时
{
ss=!ss; //闪烁变量取反
}
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_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;
buzz=0; //蜂鸣器报警提示时间到
}
}
// else buzz=1;
}
}
硬件设计
使用元器件:
单片机:STC89C52;
(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)
LED;蜂鸣器;
三极管;电阻;
6*6轻触开关;
7*7自锁开关;
3.6寸数码管;
人体感应模块;
红外接近传感器;
导线:若干;
结构图:
设计资料
01 原理图
本系统原理图采用Altium Designer19设计,具体如图!
02 程序
本设计使用软件keil5版本编程设计,资料里有安装教程,无需担心!具体如图!
03 设计报告
三千字设计报告,具体如下!
04 设计资料
资料获取请关注同名公众号,全部资料包括程序(含注释)、PCB电路图、AD原理图、设计报告、任务书、元件清单、结构图等。具体内容如下,全网最全! !
点赞分享一起学习成长。