系统组成部分
-
51单片机核心控制模块
- 使用51单片机(如STC89C51)作为主控制器。
-
按键输入模块
- 用于实现灯光亮度调整和时间设置。
- 按键有5个:调节亮度、时间设置模式确认、时间调整、时间加减。
-
亮度调节模块
- 通过PWM控制LED灯的亮度。
- 提供低、中、高三个亮度档位(不同占空比)。
-
人感传感器模块
- 使用红外传感器(如HC-SR501)感知有人或无人。
- 在检测到人时激活台灯;无人时关闭台灯。
-
时间显示与设置模块
- 使用DS1306 RTC模块读取当前时间。
- 显示时间在0.96寸OLED屏幕上(I2C通信接口)。
- 提供按键用于时间的设置和调整。
系统工作原理
基本工作流程
-
初始状态
- 系统通电,51单片机初始化各模块。
- 人感传感器初始化,检测是否有人。
- DS1306 RTC模块初始化,51单片机读取当前时间并显示在OLED屏幕上。
-
人感传感器检测
- 红外传感器实时检测环境中是否有人。
- 检测到人时,51单片机使能台灯亮起。
- 无人时,台灯关闭以节省电能。
-
亮度调整
- 在有人状态下,按下增加亮度/减少亮度按键,可以在低、中、高三个亮度档位之间切换。
- 51单片机通过PWM波的占空比调节LED灯的亮度。
-
时间显示与设置
- OLED屏幕实时显示DS1306提供的当前时间。
- 用户可通过按键进入时间设置模式(长按某键,如确认键)。
- 进入时间设置模式后,通过增加/减少按键调整小时和分钟,确认键保存设置。
硬件连接图示(简要描述)
-
51单片机
- 输入:连接按键、红外传感器数据线、DS1306 RTC模块(I2C接口)。
- 输出:连接OLED屏幕(I2C接口)、PWM控制LED灯。
-
红外传感器HC-SR501
- VCC接单片机的5V电源。
- GND接地。
- OUT接单片机的某I/O口,用于检测是否有人。
-
按键模块
- 多个按键分别接入单片机的I/O口,对应不同功能(亮度增加、减少,时间设置和调整)。
-
DS1306 RTC模块
- VCC接单片机的5V电源。
- GND接地。
- SCL和SDA接单片机的I2C总线。
-
0.96寸OLED屏
- VCC接单片机的5V电源。
- GND接地。
- SCL和SDA接单片机的I2C总线。
-
LED灯具
- 接单片机的PWM控制端口。
- 通过调整PWM占空比来控制亮度。
系统操作说明
- 开机后,系统会先读取当前时间并在OLED屏幕显示。
- 默认灭灯,需要人感传感器检测到人后,台灯点亮。
- 灯亮情况下,用户可通过按键调节灯的亮度。三个亮度档次可循环切换。
- 在任何时候,用户均可进入(按键触发)时间设置模式来调整当前时间。
- 时间设置完成后,确认保存并返回正常状态。
该系统通过简单的硬件连接和软件控制,实现智能台灯控制、时间显示和时间设置等功能,提供便捷的用户体验和智能化的节能照明解决方案。
系统完整主程序代码
#include "regx52.h"
#include "oled.h"
#include "DS1302.h"
#include "key.h"
#include "Timer0.h"
unsigned char time, KeyNum, MODE, TimeSetSelect, Flag500Ms = 0;
unsigned char LEDBrightness = 0; // 亮度等级
unsigned int PWM_Count = 0; // 用于PWM计数
unsigned int person = 0; // 1 有人 0 无人
sbit LED = P0^0; // 假设LED连接在P1.1上
void LED_Light(unsigned char num)
{
switch (num)
{
case 0:
LEDBrightness = 0;
OLED_ShowString(4, 3, "OFF ");
break;
case 1:
LEDBrightness = 33; // 假设大约33%占空比
OLED_ShowString(4, 2, "33% brightness");
break;
case 2:
LEDBrightness = 66; // 假设大约66%占空比
OLED_ShowString(4, 2, "66% brightness");
break;
case 3:
LEDBrightness = 100; // 100%亮度
OLED_ShowString(4, 2, "100% brightness");
break;
}
}
void TimeShow()
{
DS1302_TimeRead();
OLED_ShowNum(1, 1, DS1302_Time[0], 2);
OLED_ShowNum(1, 4, DS1302_Time[1], 2);
OLED_ShowNum(1, 7, DS1302_Time[2], 2);
OLED_ShowNum(2, 1, DS1302_Time[3], 2);
OLED_ShowNum(2, 4, DS1302_Time[4], 2);
OLED_ShowNum(2, 7, DS1302_Time[5], 2);
OLED_ShowChar(1, 3, '-');
OLED_ShowChar(1, 6, '-');
OLED_ShowChar(2, 3, ':');
OLED_ShowChar(2, 6, ':');
}
void TimeSet()
{
if (KeyNum == 2)
{
TimeSetSelect++;
TimeSetSelect %= 6;
}
if (KeyNum == 3)
{
DS1302_Time[TimeSetSelect]++;
if (DS1302_Time[0] > 99) { DS1302_Time[0] = 0; } //年越界判断
if (DS1302_Time[1] > 12) { DS1302_Time[1] = 1; } //月越界判断
if (DS1302_Time[1] == 1 || DS1302_Time[1] == 3 || DS1302_Time[1] == 5 || DS1302_Time[1] == 7 || //大月判断
DS1302_Time[1] == 8 || DS1302_Time[1] == 10 || DS1302_Time[1] == 12)
{
if (DS1302_Time[2] > 31) { DS1302_Time[2] = 1; } //日越界判断
}
else if (DS1302_Time[1] == 4 || DS1302_Time[1] == 6 || DS1302_Time[1] == 9 || DS1302_Time[1] == 11) //小月判断
{
if (DS1302_Time[2] > 30) { DS1302_Time[2] = 1; } //日越界判断
}
else if (DS1302_Time[1] == 2)
{
if (DS1302_Time[0] % 4 == 0) //闰年
{
if (DS1302_Time[2] > 29) { DS1302_Time[2] = 1; } //日越界判断
}
else //非闰年
{
if (DS1302_Time[2] > 28) { DS1302_Time[2] = 1; } //日越界判断
}
}
if (DS1302_Time[3] > 23) { DS1302_Time[3] = 0; } //时越界判断
if (DS1302_Time[4] > 59) { DS1302_Time[4] = 0; } //分越界判断
if (DS1302_Time[5] > 59) { DS1302_Time[5] = 0; } //秒越界判断
}
if (KeyNum == 4)
{
DS1302_Time[TimeSetSelect]--;
if (DS1302_Time[0] < 0) { DS1302_Time[0] = 99; }//年越界判断
if (DS1302_Time[1] < 1) { DS1302_Time[1] = 12; } //月越界判断
if (DS1302_Time[1] == 1 || DS1302_Time[1] == 3 || DS1302_Time[1] == 5 || DS1302_Time[1] == 7 || //大月判断
DS1302_Time[1] == 8 || DS1302_Time[1] == 10 || DS1302_Time[1] == 12)
{
if (DS1302_Time[2] < 1) { DS1302_Time[2] = 31; } //日越界判断
}
else if (DS1302_Time[1] == 4 || DS1302_Time[1] == 6 || DS1302_Time[1] == 9 || DS1302_Time[1] == 11) //小月判断
{
if (DS1302_Time[2] < 1) { DS1302_Time[2] = 30; } //日越界判断
}
else if (DS1302_Time[1] == 2)
{
if (DS1302_Time[0] % 4 == 0) //闰年
{
if (DS1302_Time[2] < 1) { DS1302_Time[2] = 29; } //日越界判断
}
else //非闰年
{
if (DS1302_Time[2] < 1) { DS1302_Time[2] = 28; } //日越界判断
}
}
if (DS1302_Time[3] < 0) { DS1302_Time[3] = 23; } //时越界判断
if (DS1302_Time[4] < 0) { DS1302_Time[4] = 59; } //分越界判断
if (DS1302_Time[5] < 0) { DS1302_Time[5] = 59; } //秒越界判断
}
if (TimeSetSelect == 0 && Flag500Ms == 1) { OLED_ShowString(1, 1, " "); }
else { OLED_ShowNum(1, 1, DS1302_Time[0], 2); }
if (TimeSetSelect == 1 && Flag500Ms == 1) { OLED_ShowString(1, 4, " "); }
else { OLED_ShowNum(1, 4, DS1302_Time[1], 2); }
if (TimeSetSelect == 2 && Flag500Ms == 1) { OLED_ShowString(1, 7, " "); }
else { OLED_ShowNum(1, 7, DS1302_Time[2], 2); }
if (TimeSetSelect == 3 && Flag500Ms == 1) { OLED_ShowString(2, 1, " "); }
else { OLED_ShowNum(2, 1, DS1302_Time[3], 2); }
if (TimeSetSelect == 4 && Flag500Ms == 1) { OLED_ShowString(2, 4, " "); }
else { OLED_ShowNum(2, 4, DS1302_Time[4], 2); }
if (TimeSetSelect == 5 && Flag500Ms == 1) { OLED_ShowString(2, 7, " "); }
else { OLED_ShowNum(2, 7, DS1302_Time[5], 2); }
}
void main()
{
OLED_Init();
DS1302_Init();
DS1302_TimeSet();
Timer0_Init();
while (1)
{
KeyNum = key();
if (KeyNum == 6)
{
person = !person;
}
if (person == 1) //有人
{
OLED_ShowString(3, 4, "Wellcome!");
if (KeyNum == 1)
{
if (MODE == 0) //当前模式为 时钟运行模式
{
MODE = 1; //切换模式为 调节时间模式
}
else if (MODE == 1) //当前模式为 调节时间模式
{
MODE = 0; //切换模式为 时钟运行模式
TimeSetSelect = 0;
DS1302_TimeSet();
}
}
switch (MODE)
{
case 0: TimeShow(); break;
case 1: TimeSet(); break;
default: break;
}
OLED_ShowNum(3, 1, KeyNum, 2);
// 如果按键为5,增加LED亮度
if (KeyNum == 5)
{
LEDBrightness++;
LEDBrightness %= 4; // 使亮度等级在0-3之间循环
LED_Light(LEDBrightness);
}
}
else
{
OLED_ShowString(4, 1, " OFF ");
OLED_ShowString(1, 1, " ");
OLED_ShowString(2, 1, " ");
OLED_ShowString(3, 1, " ");
LED = 0; // 低电平,完全关闭LED
}
}
}
unsigned int Count = 0;
void Timer0_Rountine(void) interrupt 1
{
TL0 = 0xCB; // 低字节
TH0 = 0xB2; // 高字节
Count++;
PWM_Count++;
// 如果检测到没有人时,将PWM信号停止,确保LED完全关闭
if (person == 0)
{
LED = 0; // 低电平,完全关闭LED
return ; // 跳过剩余代码
}
if (Count >= 10)
{
Count = 0;
Flag500Ms = !Flag500Ms;
}
if (PWM_Count >= 100)
{
PWM_Count = 0;
}
// 控制LED亮度的PWM信号
if (PWM_Count < LEDBrightness)
{
LED = 1; // 高电平
}
else
{
LED = 0; // 低电平
}
}
系统protues仿真图
系统详细讲解视频
基于51单片机智能台灯控制系统设计
基于51单片机智能台灯控制系统设计 毕设项目 单片机课程设计