Bootstrap

单片机课程设计(基于51单片机智能台灯控制系统设计)

系统组成部分

  1. 51单片机核心控制模块

    • 使用51单片机(如STC89C51)作为主控制器。
  2. 按键输入模块

    • 用于实现灯光亮度调整和时间设置。
    • 按键有5个:调节亮度、时间设置模式确认、时间调整、时间加减。
  3. 亮度调节模块

    • 通过PWM控制LED灯的亮度。
    • 提供低、中、高三个亮度档位(不同占空比)。
  4. 人感传感器模块

    • 使用红外传感器(如HC-SR501)感知有人或无人。
    • 在检测到人时激活台灯;无人时关闭台灯。
  5. 时间显示与设置模块

    • 使用DS1306 RTC模块读取当前时间。
    • 显示时间在0.96寸OLED屏幕上(I2C通信接口)。
    • 提供按键用于时间的设置和调整。

系统工作原理

基本工作流程
  1. 初始状态

    • 系统通电,51单片机初始化各模块。
    • 人感传感器初始化,检测是否有人。
    • DS1306 RTC模块初始化,51单片机读取当前时间并显示在OLED屏幕上。
  2. 人感传感器检测

    • 红外传感器实时检测环境中是否有人。
    • 检测到人时,51单片机使能台灯亮起。
    • 无人时,台灯关闭以节省电能。
  3. 亮度调整

    • 在有人状态下,按下增加亮度/减少亮度按键,可以在低、中、高三个亮度档位之间切换。
    • 51单片机通过PWM波的占空比调节LED灯的亮度。
  4. 时间显示与设置

    • OLED屏幕实时显示DS1306提供的当前时间。
    • 用户可通过按键进入时间设置模式(长按某键,如确认键)。
    • 进入时间设置模式后,通过增加/减少按键调整小时和分钟,确认键保存设置。

硬件连接图示(简要描述)

  1. 51单片机

    • 输入:连接按键、红外传感器数据线、DS1306 RTC模块(I2C接口)。
    • 输出:连接OLED屏幕(I2C接口)、PWM控制LED灯。
  2. 红外传感器HC-SR501

    • VCC接单片机的5V电源。
    • GND接地。
    • OUT接单片机的某I/O口,用于检测是否有人。
  3. 按键模块

    • 多个按键分别接入单片机的I/O口,对应不同功能(亮度增加、减少,时间设置和调整)。
  4. DS1306 RTC模块

    • VCC接单片机的5V电源。
    • GND接地。
    • SCL和SDA接单片机的I2C总线。
  5. 0.96寸OLED屏

    • VCC接单片机的5V电源。
    • GND接地。
    • SCL和SDA接单片机的I2C总线。
  6. LED灯具

    • 接单片机的PWM控制端口。
    • 通过调整PWM占空比来控制亮度。

系统操作说明

  1. 开机后,系统会先读取当前时间并在OLED屏幕显示。
  2. 默认灭灯,需要人感传感器检测到人后,台灯点亮。
  3. 灯亮情况下,用户可通过按键调节灯的亮度。三个亮度档次可循环切换。
  4. 在任何时候,用户均可进入(按键触发)时间设置模式来调整当前时间。
  5. 时间设置完成后,确认保存并返回正常状态。

该系统通过简单的硬件连接和软件控制,实现智能台灯控制、时间显示和时间设置等功能,提供便捷的用户体验和智能化的节能照明解决方案。

系统完整主程序代码

#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单片机智能台灯控制系统设计 毕设项目 单片机课程设计

;