【STC51项目开源】STC51单片机智能台灯控制系统
目录
一、设计背景和意义
1.1设计背景:
1.2设计意义:
二、实物展示
三、硬件功能介绍
2.1 硬件清单:
2.2 功能介绍:
四、软件设计流程图
五、硬件PCB展示
六、软件主函序展示
七、单片机实物资料
资料获取 查看主页介绍:兆龙电子单片机设计
一、设计背景和意义
1.1设计背景:
在智能家居与健康照明理念日益普及的当下,传统台灯存在诸多功能局限。多数家庭仍在使用手动开关、固定亮度的普通台灯,既无法根据环境光线变化自动调节亮度以保护视力,也缺乏定时提醒、人体感应启停等智能化功能,难以满足现代用户(尤其是学生、办公人群)对健康照明、便捷操作、节能降耗的多元化需求。
现有智能台灯方案常存在成本较高、功能冗余或兼容性不足的问题,部分产品依赖复杂的 APP 控制,操作门槛较高,且难以适配不同使用场景(如学习、阅读、休憩)的光照需求。随着人们对眼部健康重视程度提升及对家居设备智能化操作需求的增加,单一功能、手动调节的传统台灯已无法满足日常使用需求。基于此,本设计以STC51 单片机为核心,融合光敏传感器、人体红外传感器、按键模块与 PWM 调光技术,构建低成本、高实用性的智能台灯控制系统,以解决传统台灯中亮度调节不智能、操作便捷性差、能耗较高、缺乏健康照明辅助功能的问题。
1.2设计意义:
本设计通过整合多场景感知、智能调光与人性化辅助功能,具有多重实用价值与技术实践意义。从用户体验与健康防护角度,提供环境光自适应调光(根据外界光线自动调节亮度,避免强光刺眼或弱光伤眼)、人体感应自动启停(人来灯亮、人走延时关灯)、定时提醒(如学习 45 分钟后提醒休息,保护视力)等功能,覆盖学习、办公、休憩等核心使用场景,尤其多传感器协同感知与精准调光功能,大幅提升了台灯使用的舒适性、便捷性与健康防护性,有效减少眼部疲劳。
从节能与实用性角度,借助人体感应与智能调光技术实现 “按需照明”,避免传统台灯因忘记关灯导致的能源浪费,同时通过按键模块支持手动切换光照模式(如 “学习模式” 高亮度、“阅读模式” 暖光、“休憩模式” 低亮度),兼顾智能化与手动操作需求,符合现代家居 “节能 + 实用” 的双重理念。从技术实践层面,探索了 STC51 单片机与多类型传感器(光敏、人体红外)、PWM 调光模块的协同工作机制,方案成本低、电路结构简洁、易于组装与调试,为低成本智能照明设备开发提供了可参考的集成方案,推动普通台灯从 “手动操作” 向 “智能感知 + 健康照明” 升级,具有较强的家庭普及价值与教学实践意义。
二、实物展示
下方为实物演示视频
【开源】基于STC51单片机智能台灯控制系统
下方为实物展示图片
三、硬件功能介绍
2.1 硬件清单:
- STC89C52
- LCD1602显示屏
- 光照采集电路
- 蜂鸣器报警
- 人体感应模块
- DS1302时钟模块
- 超声波传感器
- ADC0832模数转换
- USB台灯
- ESP8266 WIFI模块
2.2 功能介绍:
(1)亮度自动控制:基于光照值自动调节台灯亮度(0-9档),遵循 “光线越暗,台灯越亮” 的逻辑,且该功能仅在检测到人体时生效,无人状态下台灯自动关闭;
(2)人走灯灭自动控制:通过人体感应传感器检测周围是否有人,检测到无人后,延迟设定时长后台灯自动关闭,实现 “人来灯亮、人走灯灭” 效果;
(3)坐姿规范报警:若检测到人体坐姿不规范(如距离台灯过近),将触发蜂鸣器报警提醒;
(4)时间显示与闹钟功能:实时显示当前时间(时分秒),当预设闹钟时间到达时,蜂鸣器触发报警提醒,报警将在 1 分钟后自动关闭,也可通过按键手动关闭报警。
手动模式:
(5)灯光挡位调节:支持 0-10 档亮度调节,按按键 2增加亮度挡位,按按键 3降低亮度挡位;
(6)人走灯灭延时设置:默认延时时间为 30 秒,可通过按键自定义调节延时时长;
(7)距离报警值设置:按按键 2增加距离报警阈值,按按键 3减小距离报警阈值;
(8)时间设置:可通过按键设置当前时间与闹钟时间。
蓝牙功能
系统将当前运行数据(亮度、时间、距离模式等)传输至蓝牙 APP,可通过 APP 远程调节台灯亮度档位,以及切换系统工作模式
四、软件设计流程图
五、硬件PCB展示
六、软件主函序展示
#include <reg52.h>
#include "LCD1602.h"//包含LCD1602头文件
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned intsbit Lamp = P1^7; // 台灯控制引脚
sbit Key1 = P1^3; // 按键1,模式切换按键
sbit Key2 = P1^4; // 按键2,选择
sbit Key3 = P1^5; // 按键3,亮度增加按键
sbit Key4 = P1^6; // 按键4, 亮度减少按键sbit Module = P3^6; // 人体红外检测模块
//ADC0832引脚定义
sbit CS = P3^7; // ADC0832的CS引脚
sbit CLK = P2^7; // ADC0832的CLK引脚
sbit DIDO = P2^6; // ADC0832的DI/DO引脚
uchar gCount=0;// 全局计数变量
uchar gIndex; // 亮度变量,0(最暗)-10档
uint gTime=0;// 计时变量,用于计时多久没检测到有人
uchar model=0; //自/手动模式切换
uchar key_can; //按键值
uchar Selected=0; //选择
bit flag_500ms=0 ;
uchar gbiao=0,TimeSetFlashFlag=0;//光标
unsigned long count=60000;//没检测到有人多长时间灭
void TimerInit();
void ManualControl();
void AutoControl(uchar num);
uchar Get_AD_Result();
unsigned char Key();//独立按键
void key_with();
//ms延时函数
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms--){_nop_();i = 2;j = 199;
do{
while (--j);} while (--i);}
}void main()
{uchar ret=0;P0 = P1 = P2 = P3 = 0xff; //
TimerInit(); // 定时器初始化ret=Get_AD_Result(); // 获取AD采集结果(环境光照强度)
AutoControl(ret); // 上电先进行一次自动亮度控制
AutoControl(ret+7);
LCD_Init();//lcd1602while(1){ key_can=Key(); //按键扫描
key_with();
if(model) //手动操作{
switch (Selected){
case 0:
LCD_ShowString(1,13,"Manu");
break;
case 1:
LCD_ShowString(1,4,"Light_Time");
LCD_ShowNum(2,7,count/1000,3);LCD_ShowString(2,10,"s");
break;
case 2:
ManualControl();//手动控制灯光
break;} }
else{
LCD_ShowString(1,13,"Auto");
if(flag_500ms){flag_500ms=0;
if(gTime<count) //有人在的情况才控制光照{ret= Get_AD_Result();//获取AD采集结果(环境光照强度)
AutoControl(ret); //自动亮度控制 }}
/*检测是否有人*/
if(Module==0){gTime=0; // 检测到有人,则把60秒计时清零LCD_ShowString(2,1,"Ren:Yes");}
else{
LCD_ShowString(2,1,"Ren:No "); } LCD_ShowString(1,1,"GZ:");
LCD_ShowString(1,7,"Lx");
LCD_ShowString(2,14,"D");
LCD_ShowString(2,12,"s");
LCD_ShowNum(1, 4, ret,3);
LCD_ShowNum(2, 15, gIndex,1);
LCD_ShowNum(2,9,gTime/1000,3);}}
}
// 定时器0服务程序,1毫秒
void Timer0(void) interrupt 1
{
static unsigned int T0Count;TH0 = 252;TL0 = 24; //1msT0Count++;
if(T0Count>=500)//每500ms进入一次{T0Count=0;flag_500ms=1;}gTime++; // 每1毫秒,gTime变量加1gCount++; // 每1毫秒,gCount变量加1
if(gCount==10) // 如果gCount加到10了{gCount=0; // 则将gCount清零,进入新一轮的计数
if(gIndex!=0) // 如果说台灯不是最暗的(熄灭){Lamp=0; // 则把台灯点亮}}
if(gCount==gIndex) // 如果gCount计数到和gIndex一样了{
if(gIndex!=9) // 如果说台灯不是最亮的{Lamp=1; // 则把台灯熄灭}}
}// 定时器初始化
void TimerInit()
{TMOD = 0x01; // 使用定时器0,工作方式1 TH0 = 252; // 给定时器0的TH0装初值TL0 = 24; // 给定时器0的TL0装初值 ET0 = 1; // 定时器0中断使能EA = 1; // 打开总中断TR0 = 1; // 启动定时器0
}
//获取AD转换结果
uchar Get_AD_Result()
{uchar i,dat1 = 0,dat2 = 0;
//起始控制位CS = 0;CLK = 0;DIDO = 1; _nop_(); _nop_();CLK = 1; _nop_(); _nop_();
//第一个下降沿之前 设DI=1/0
//选择单端/差分(SGL/DIF)模式中的单端输入模式CLK = 0; DIDO=1; _nop_();_nop_();CLK = 1; _nop_();_nop_();
//第二个下降沿之前 设DI=0/1 选择CH0/CH1CLK = 0;DIDO = 0; _nop_();_nop_();CLK = 1;DIDO = 1; _nop_();_nop_();
//第三个下降沿之前 DI=1CLK = 0; DIDO = 1; _nop_();_nop_();
//4-11,共8个下降沿读取数据(MSB->LSB)
for(i=0;i<8;i++){CLK = 1; _nop_();_nop_();CLK = 0; _nop_();_nop_();dat1 = dat1<<1|DIDO;}
//11-18 共8个下降沿读取数据(LSB->MSB)
for(i=0;i<8;i++){dat2 = dat2|((uchar)(DIDO)<<i);CLK = 1; _nop_();_nop_();CLK = 0; _nop_();_nop_();}CS = 1;
//如果MSB->LSB和LSB->MSB读取数据结果相同,返回读取结果,否者0
return (dat1==dat2) ? dat1 : 0 ;
}// 手动控制
void ManualControl()
{
// 亮度减少
if(Key4==0) // 如果按键2被按下去{
if(gIndex>0) // 只要当前亮度不为最低才能减少亮度{gIndex--; // 亮度降低一档
Delay(300); // 延时0.3秒}}
// 亮度增加
if(Key3==0) // 如果按键3被按下去{
if(gIndex<9) // 只要当前亮度不为最高才能增加亮度{gIndex++; // 亮度增加一档
Delay(300); // 延时0.3秒}}
LCD_ShowString(1,5,"Lamp_DW");
LCD_ShowString(2,8,"D");
LCD_ShowNum(2,9,gIndex,1);
}
// 自动控制
void AutoControl(uchar num)
{
if(num<59) // 最亮gIndex=9;
else if((num>65)&&(num<81)) // 第二亮gIndex=8;
else if((num>87)&&(num<103)) // 第三亮gIndex=7;
else if((num>109)&&(num<125))gIndex=6;
else if((num>131)&&(num<147))gIndex=5;
else if((num>153)&&(num<169))gIndex=4;
else if((num>175)&&(num<191))gIndex=3;
else if((num>197)&&(num<213))gIndex=2;
else if((num>219)&&(num<235))gIndex=1;
else if(num>241) // 最暗gIndex=0;
}
//独立按键程序
unsigned char Key()
{
unsigned char KeyNumber=0;if(Key1==0){Delay(10);while(Key1==0);Delay(10);KeyNumber=1;}
if(Key2==0){Delay(10);while(Key2==0);Delay(10);KeyNumber=2;}
if(Key3==0){Delay(10);if(Key3==0);Delay(10);KeyNumber=3;}
if(Key4==0){Delay(10);if(Key4==0);Delay(10);KeyNumber=4;}return KeyNumber;
}
//按键设置函数
void key_with()
{
if(key_can == 1)//按键1 {
if(Selected==0)//模式切换{model++; model%=2;}}
else if(key_can == 2)//按键2-设置 {
if(model)//手动操作下{Selected++;
if(Selected>=3) {Selected=0;model=0;}
LCD_WriteCommand(0x01);//光标复位,清屏}}
else if(key_can == 3) //加{
if(Selected==1) //页面一{count+=1000; //距离阈值加if(count>=600000)count=0;}}
else if(key_can == 4) //减{
if(Selected==1) //页面一{if(count>0)count-=1000;}}
}