基于51单片机pwm调光护眼台灯智能检测光强光控灯设计proteus仿真原理图PCB

news2025/7/7 1:16:38

功能:
0.本系统采用STC89C52作为单片机
1.LCD1602液晶实时显示当前时间/模式/亮度等级
2.按’切换’键可切换四种不同的模式
a) 自动开关,自动调节亮度
b) 手动开关,自动调节亮度
c) 自动开关,手动调节亮度
d) 手动开关,手动调节亮度
3.长按’切换’键可打开或关闭LED小灯
4.按’增大’或’减小’键可调节LED亮度等级
5.采用DC002作为电源接口可直接输入5V给整个系统供电

原理图:
在这里插入图片描述

PCB :
在这里插入图片描述

主程序:

#define _MAIN_C
#include <reg52.h>
#include <stdio.h>
#include "main.h"
#include "delay.h"
#include "eeprom52.h"
#include "tlc0832.h"
#include "ds1302.h"
#include "lcd1602.h"
#include "date.h"

// 管脚声明
sbit IR_SCAN = P1^6;
sbit KEY_SUB = P3^6;
sbit KEY_ADD = P3^4;
sbit KEY_MODE = P3^5;
sbit KEY_SET = P3^3;
sbit LED_PWM = P2^1;
sbit BUZZER = P2^0;


extern unsigned char timeBufBcd[8];
extern unsigned char timeBufDec[8];

unsigned char dispRow0[] = "  /  /  ";
unsigned char dispRow1[] = "  :  :  ";
unsigned char g_setLocation = 0;
unsigned long highT0RH;
unsigned long highT0RL;
unsigned long lowT0RH;
unsigned long lowT0RL;
unsigned char g_PWMdutyCycle = 50;
unsigned char isNew;
unsigned long minuteBuf;
bit g_setTimeFlag = 0;
bit g_OffFlag = 0;
bit g_dispOn = 0;
bit g_getADData = 0;


void DispTime(); //显示时间
void Init_Timer0(); //定时器0初始化
void Init_Timer1(); //定时器1初始化
void KeyPress(); //按键处理
void SetTime(); //设定时间
void SetPWM(unsigned int freq, unsigned char dutyCycle); //PWM设定
void DispLED(); //显示模式和光照等级

CreatByte mode;

// 主函数
main()
{
    unsigned long PWMfreq = 100;
    unsigned long adData = 0;
    unsigned long adDataBuf = 0;
    static unsigned char getADDataCnt = 0;

    
    // 初始化
    Init_EEPROM();
    DS1302_Init();
    if (!isNew)
    {
        DS1302_ReadTime();
    }
    else
    {
        DS1302_WriteTime();
    }
    LCD_Init();
    LCD_CLear();

    SetPWM(PWMfreq, g_PWMdutyCycle);
    Init_Timer0();
    Init_Timer1();

    DispTime();
    DispLED();

    while (1)
    {
        SetPWM(PWMfreq, g_PWMdutyCycle); //设置PWM频率和占空比
        if (g_dispOn)
        {
            DispTime(); //显示时间
            DispLED(); //显示模式和灯光等级
            g_dispOn = 0;
        }

        if (g_setTimeFlag)
        {
            SetTime(); //设置时间
        }
        else
        { 
            DS1302_ReadTime(); //读取时间
        }
        
        if (g_isAutoOff) //自动开关模式
        {
            if (g_OffFlag == 1)
            {
                LED_PWM = 1;
                TR0 = 0; //关闭定时器0计数
            }
            else
            {
                TR0 = 1; //开启定时器0计数
            }
            
            if (IR_SCAN == 0) //有人时一直给最新的秒时间
            {
                minuteBuf = timeBufDec[6];
            }
            else //没人时,1分钟后关闭台灯
            {
                if (minuteBuf == timeBufDec[6] + 1)
                {
                    g_OffFlag = 1;
                }
            }
        }
        
        if (g_isAutoAjust == 1 && g_getADData == 1) //自动调整灯光亮度模式
        {
            adData = ReadADC(AIN0_GND);
            adData = 100 * adData / 255; //读取灯光亮度
            if (getADDataCnt < 5) //累加5次
            {
                adDataBuf = adDataBuf + adData;
                getADDataCnt++;
            }
            else //求平均
            {
                adDataBuf = adDataBuf / getADDataCnt;
                if (adDataBuf >= 95)
                {
                    adDataBuf = 95;
                }
                else if (adDataBuf <= 5)
                {
                    adDataBuf = 5;
                }
                g_PWMdutyCycle = adDataBuf;
                adDataBuf = 0;
                getADDataCnt = 0;
            }
            g_getADData = 0;
        }
        
        KeyPress(); //按键处理
    }
}

void DispTime()
{

    dispRow0[0] = timeBufDec[1] / 10 +'0'; //年
    dispRow0[1] = timeBufDec[1] % 10 +'0';
    dispRow0[3] = timeBufDec[2] / 10 +'0'; //月
    dispRow0[4] = timeBufDec[2] % 10 +'0';
    dispRow0[6] = timeBufDec[3] / 10 +'0'; //日
    dispRow0[7] = timeBufDec[3] % 10 +'0';
    dispRow1[0] = timeBufDec[4] / 10 +'0'; //时
    dispRow1[1] = timeBufDec[4] % 10 +'0';
    dispRow1[3] = timeBufDec[5] / 10 +'0'; //分
    dispRow1[4] = timeBufDec[5] % 10 +'0';
    dispRow1[6] = timeBufDec[6] / 10 +'0'; //秒
    dispRow1[7] = timeBufDec[6] % 10 +'0';

    LCD_WriteStr(0, 0, dispRow0); //显示日期
    LCD_WriteStr(0, 1, dispRow1); //显示时间

    switch (timeBufDec[7]) //显示星期
    {
        case 1: LCD_WriteStr(10, 0, " Sun."); break;
        case 2: LCD_WriteStr(10, 0, " Mon."); break;
        case 3: LCD_WriteStr(10, 0, " Tue."); break;
        case 4: LCD_WriteStr(10, 0, " Wed."); break;
        case 5: LCD_WriteStr(10, 0, "Thur."); break;
        case 6: LCD_WriteStr(10, 0, " Fri."); break;
        case 7: LCD_WriteStr(10, 0, " Sat."); break;
        default: LCD_WriteStr(10, 0, " Sun."); break;
    }
}

void SetTime()
{
    TR1 = 0;
    LCD_WriteCommand(0x0F, 0);
    // LCD_WriteCommand(0x0C, 0);
    switch (g_setLocation)
    {
        case 1: LCD_WriteCommand(0x80 + 1, 0); break;
        case 2: LCD_WriteCommand(0x80 + 4, 0); break;
        case 3: LCD_WriteCommand(0x80 + 7, 0); break;
        case 4: LCD_WriteCommand(0x80 + 0x40 + 1, 0); break;
        case 5: LCD_WriteCommand(0x80 + 0x40 + 4, 0); break;
        case 6: LCD_WriteCommand(0x80 + 0x40 + 7, 0); break;
        case 7: LCD_WriteCommand(0x80 + 14, 0); break;
        case 8: 
        {
            LCD_WriteCommand(0x0C, 0);
            DS1302_WriteTime();
            g_setLocation = 0;
            g_setTimeFlag = 0;
            break;
        }
        default: ;
    }
    TR1 = 1;
}

void DispLED()
{
    if (g_isAutoOff)
    {
        LCD_WriteChar(10, 1, 'A'); //自动开关模式
    }
    else
    {
        LCD_WriteChar(10, 1, 'M'); //手动开关模式
    }

    if (g_isAutoAjust)
    {
        LCD_WriteChar(12, 1, 'A'); //自动调节亮度模式
    }
    else
    {
        LCD_WriteChar(12, 1, 'M'); //手动调节亮度模式
    }

    LCD_WriteChar(14, 1, g_PWMdutyCycle / 5 / 10 + '0');
    LCD_WriteChar(15, 1, g_PWMdutyCycle / 5 % 10 + '0');
}

void SetPWM(unsigned int freq, unsigned char dutyCycle)
{
    unsigned long totalCnt;
    unsigned long highCnt;
    unsigned long lowCnt;

    totalCnt = 11059200 / freq / 12; // (1/freq) / (12/11059200);
    highCnt = totalCnt * dutyCycle / 100;
    lowCnt = totalCnt - highCnt;
    highCnt = 65536 - highCnt;
    lowCnt = 65536 - lowCnt;
    highT0RH = highCnt / 256;
    highT0RL = highCnt % 256;
    lowT0RH = lowCnt / 256;
    lowT0RL = lowCnt % 256;
}

void KeyPress()
{
    static unsigned int keyCnt;

    if (!KEY_SET) //设置键按下
    {
        DelayMs(10);
        if (!KEY_SET)
        {
            if (!g_setTimeFlag)
            {
                g_setTimeFlag = 1;
            }
            g_setLocation++;
            BUZZER = 0;
            DelayMs(10);
            BUZZER = 1;
        }
        while (!KEY_SET);
    }

    if (!KEY_ADD) //加键按下
    {
        DelayMs(180);
        if (!KEY_ADD)
        {
            if (!g_setTimeFlag)
            {
                if (g_isAutoAjust == 1)
                {
                    g_isAutoAjust = 0;
                }
                g_PWMdutyCycle = g_PWMdutyCycle + 5;
                if (g_PWMdutyCycle >= 95)
                {
                    g_PWMdutyCycle = 95;
                }
                Write_EEPROM();
            }
            else
            {
                switch (g_setLocation)
                {
                case 1:
                {
                    timeBufDec[1]++;
                    if (timeBufDec[1] >= 100)
                    {
                        timeBufDec[1] = 0;
                    }
                    break;
                }
                case 2:
                {
                    timeBufDec[2]++;
                    if (timeBufDec[2] >= 13)
                    {
                        timeBufDec[2] = 1;
                    }
                    break;
                }
                case 3:
                {
                    timeBufDec[3]++;
                    if (timeBufDec[3] >= YDay(timeBufDec[1], timeBufDec[2]) + 1)
                    {
                        timeBufDec[3] = 1;
                    }
                    break;
                }
                case 4:
                {
                    timeBufDec[4]++;
                    if (timeBufDec[4] >= 24)
                    {
                        timeBufDec[4] = 0;
                    }
                    break;
                }
                case 5:
                {
                    timeBufDec[5]++;
                    if (timeBufDec[5] >= 60)
                    {
                        timeBufDec[5] = 0;
                    }
                    break;
                }
                case 6:
                {
                    timeBufDec[6]++;
                    if (timeBufDec[6] >= 60)
                    {
                        timeBufDec[6] = 0;
                    }
                    break;
                }
                case 7:
                {
                    timeBufDec[7]++;
                    if (timeBufDec[7] > 7)
                    {
                        timeBufDec[7] = 1;
                    }
                    break;
                }
                default:;
                }
            }
            BUZZER = 0;
            DelayMs(10);
            BUZZER = 1;
        }
        //while (!KEY_ADD);
    }

    if (!KEY_SUB) //减键按下
    {
        DelayMs(180);
        if (!KEY_SUB)
        {
            if (!g_setTimeFlag)
            {
                if (g_isAutoAjust == 1)
                {
                    g_isAutoAjust = 0;
                }
                g_PWMdutyCycle = g_PWMdutyCycle - 5;
                if (g_PWMdutyCycle <= 5)
                {
                    g_PWMdutyCycle = 5;
                }
                Write_EEPROM();
            }
            else
            {
                switch (g_setLocation)
                {
                case 1:
                {
                    if (timeBufDec[1] == 0)
                    {
                        timeBufDec[1] = 100;
                    }
                    timeBufDec[1]--;
                    break;
                }
                case 2:
                {
                    timeBufDec[2]--;
                    if (timeBufDec[2] < 1)
                    {
                        timeBufDec[2] = 12;
                    }
                    break;
                }
                case 3:
                {
                    timeBufDec[3]--;
                    if (timeBufDec[3] < 1)
                    {
                        timeBufDec[3] = YDay(timeBufDec[1], timeBufDec[2]);
                    }
                    break;
                }
                case 4:
                {
                    if (timeBufDec[4] == 0)
                    {
                        timeBufDec[4] = 24;
                    }
                    timeBufDec[4]--;
                    break;
                }
                case 5:
                {
                    if (timeBufDec[5] == 0)
                    {
                        timeBufDec[5] = 60;
                    }
                    timeBufDec[5]--;
                    break;
                }
                case 6:
                {

                    if (timeBufDec[6] == 0)
                    {
                        timeBufDec[6] = 60;
                    }
                    timeBufDec[6]--;
                    break;
                }
                case 7:
                {
                    timeBufDec[7]--;
                    if (timeBufDec[7] < 1)
                    {
                        timeBufDec[7] = 7;
                    }
                    break;
                }
                default:;
                }
            }
            BUZZER = 0;
            DelayMs(10);
            BUZZER = 1;
        }
        //while (!KEY_SUB);
    }
    
    if (!KEY_MODE) //模式键按下
    {
        DelayMs(20);
        while (!KEY_MODE)
        {
            DelayMs(20);
            keyCnt++;
            if (keyCnt >= 50)
            {
                break;
            }
        }
        if (keyCnt >= 50) 
        {
            if (TR0 == 1) // 长按关灯
            {
                g_isAutoOff = 0;
                LED_PWM = 1;
                TR0 = 0;
            }
            else //长按开灯
            {
                g_isAutoOff = 0;
                LED_PWM = 0;
                TR0 = 1;
            }
        }
        else
        {
            if (g_setTimeFlag)
            {
                DS1302_WriteTime();
                g_setLocation = 0;
                g_setTimeFlag = 0;
            }
            else
            {
                g_mode++;
                g_mode &= 0x03; //满4清零
                Write_EEPROM();
            }
            LCD_WriteCommand(0x0C, 0);
            BUZZER = 0;
            DelayMs(10);
            BUZZER = 1;
        }
        keyCnt = 0;
        while (!KEY_MODE);
    }
}

仿真演示视频:
https://www.bilibili.com/video/BV1ad4y1M75Y/

实物演示视频:

https://www.bilibili.com/video/BV1LW4y1v774/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/28664.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

arthas诊断工具

1.安装 linux: curl -o https://alibaba.github.io/arthas/arthas-boot.jar //是O不是零 浏览直接访问https://alibaba.github.io/arthas/arthas-boot.jar 在运行程序之前,需要运行一个java进程在内存种 java -jar arthas-boot.jar 按序号选择诊断的进程 选择序号回车 2.卸载…

​生成图片并添加文字Image.new()与ImageDraw.drawer.text()方法​

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 生成图片并添加文字 Image.new()与ImageDraw.drawer.text()方法 [太阳]选择题 以下python代码表述错误的一项是? from PIL import Image,ImageDraw,ImageFont imgImage.new(modeRGB,…

计算机网络第六章知识点回顾(自顶向下)

第六章知识点回顾1.链路层和局域网1.1网络层、链路层和物理层1.2链路层服务1.3链路层在哪儿实现&#xff1f;1.3.1网络适配器之间的通信1.4检错和纠错1.5如何检测与纠正错误&#xff1f;1.5.1编码集的检错与纠错能力1.5.2差错检测的实施1.5.3奇偶校验1.5.4循环冗余校验&#xf…

图像分割 - 区域生长

目录 1. 介绍 2. 代码详解 3. 代码 1. 介绍 分割的目的是将图像分为多个区域 常用的分割方法基于两个属性&#xff1a;不同区域间的灰度不连续性质&#xff08;Canny边缘检测等等&#xff09;、相同区域灰度的相似特征&#xff08;阈值处理、区域生长等等&#xff09; 区…

牛客网语法篇练习基础语法(一)

1.输出"Hello Nowcoder!"。开始你的编程之旅吧。 print(Hello Nowcoder!) 2.KiKi学会了print在屏幕输出信息&#xff0c;他想输出一架小飞机。请帮他编写程序输出这架小飞机。 print( *5 ** *5) print( *5 ** *5) print(**12) print(**12) print( *4 * * *4) prin…

Arduino操作MPU6050模块

MPU6050是集成三轴陀螺仪&#xff0c;三轴加速度计&#xff0c;温度传感器于一体的模块。本文档基于Adafruit_MPU6050实现MPU6050模块基本操作。 Adafruit_MPU6050库&#xff1a; https://github.com/adafruit/Adafruit_MPU6050 Adafruit_MPU6050依赖以下库&#xff0c;需要在…

Java中的char、Character和CharSequence的区别

char 与 Character char是一种基本的数据类型&#xff0c;Character是char类型的包装类&#xff0c;即通过Character创建出来的是一种对象。 Character是char的包装类&#xff0c;就像Integer和int&#xff0c;以及Long和long一样。 包装类和基本类型可以自动转换&#xff…

安泰测试-同惠TH2827精密LCR数字电桥产品性能特点

同惠(Tonghui)TH2827A/TH2827B/TH2827C型 LCR数字电桥 产品简介&#xff1a; TH2827A/TH2827B/TH2827C是具有多种功能和更高测试频率的新型LCR数字电桥&#xff0c;体积小&#xff0c;紧凑便携&#xff0c;便于上架使用。本系列仪器基本精度为0.05%&#xff0c;测试频率最高1M…

GitLab仓库管理系统安装详细步骤

前言 本案例安装 gitlab、jenkins、并部署springboot应用程序&#xff0c;所以准备了3台服务器。 服务器1&#xff1a;安装gitlab服务器2&#xff1a;安装jdk、maven、git、jenkins 因为jenkins需要jdk、maven、git服务器3&#xff1a;安装jdk。 jenkins自动部署的springboot…

多目标优化生态调度结果的预测方法研究——基于新蝙蝠算法(Matlab代码实现)

&#x1f352;&#x1f352;&#x1f352;欢迎关注&#x1f308;&#x1f308;&#x1f308; &#x1f4dd;个人主页&#xff1a;我爱Matlab &#x1f44d;点赞➕评论➕收藏 养成习惯&#xff08;一键三连&#xff09;&#x1f33b;&#x1f33b;&#x1f33b; &#x1f34c;希…

【CNN】ZFNet——让卷积神经网络不再是一个黑盒模型。

前言 ZFNet在2013年 ILSVRC 图像分类竞赛获得冠军&#xff0c;错误率11.19% &#xff0c;比2012年的AlexNet降低了5%&#xff0c;ZFNet是由 Matthew D.Zeiler 和 Rob Fergus 在 AlexNet 基础上提出的大型卷积网络。ZFNet解释了为什么卷积神经网络可以在图像分类上表现的如此出…

[MySQL]事务ACID详解

专栏简介 :MySql数据库从入门到进阶. 题目来源:leetcode,牛客,剑指offer. 创作目标:记录学习MySql学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录 1. 事务的概念 2. 事务的特性 3.事务控制语法…

【经验篇】Java使用ZMQ断线重连问题

简介 ZeroMQ是一个高性能的异步消息传递库&#xff0c;旨在用于分布式或者并发应用程序。它提供了一个消息队列&#xff0c;但与面向消息的中间件不同&#xff0c;ZeroMQ 系统可以在没有专用消息代理的情况下运行。 ZeroMQ 支持各种传输&#xff08;TCP、进程内、进程间、多播…

初步认识端口服务查询--netstat

转载连接&#xff1a;netstat详解 目录1、语法与参数概括2、输出释义2.1 以netstat -atnlp为例&#xff0c;解释输出结果中各列的含义2.2、以netstat -rn为例&#xff0c;解释输出结果中各列的含义3、实用命令4、项目中通过netstat查询某端口是否被占用netstat命令是一个监控TC…

Spring5源码3-BeanDefinition

1. BeanDefinition BeanDefinition在spring中贯穿始终&#xff0c;spring要根据BeanDefinition对象来实例化bean&#xff0c;只有把解析的标签&#xff0c;扫描的注解类封装成BeanDefinition对象&#xff0c;spring才能实例化bean beanDefinition主要实现类: ChildBeanDefini…

ADB安装及使用详解

一、ADB简介 1、什么是adb ADB 全称为 Android Debug Bridge&#xff0c;起到调试桥的作用&#xff0c;是一个客户端-服务器端程序。其中客户端是用来操作的电脑&#xff0c;服务端是 Android 设备。 ADB 也是 Android SDK 中的一个工具&#xff0c;可以直接操作管理 Androi…

K8s高可用集群搭建

K8s高可用集群搭建1 方案简介2 集群搭建2.1 安装要求2.2 准备环境2.3 master节点部署keepalived2.4 master节点部署haproxy2.5 所有节点安装docker/kubeadm/kubelet2.6 部署k8smaster012.7 安装集群网络2.8 k8smaster02加入节点2.9 k8snode01加入集群3 测试集群1 方案简介 用到…

Session-based Recommendation with Graph Neural Networks论文阅读笔记

1. Abstract &#xff08;1&#xff09;基于会话的推荐问题旨在基于匿名会话来预测用户的行为。 The problem of session-based recommendation aims to predict user actions based on anonymous sessions. &#xff08;2&#xff09; 以前的方法存在的不足&#xff1a;不足以…

day3-day4【代码随想录】长度最小的子数组

文章目录前言一、长度最小的子数组1、暴力求解&#xff1a;2、滑动窗口求解&#xff1a;二、最小覆盖子串&#xff08;乐扣76&#xff09;难难难难难三、水果成篮&#xff08;乐扣904&#xff09;四、最长重复子数组&#xff08;乐扣718&#xff09;前言 实现滑动窗口&#xf…

Android抓包工具——Fiddler

前言 &#x1f525;在平时和其他大佬交流时&#xff0c;总会出现这么些话&#xff0c;“抓个包看看就知道哪出问题了”&#xff0c;“抓流量啊&#xff0c;payload都在里面”&#xff0c;“这数据流怎么这么奇怪”。 &#x1f449;这里出现的名词&#xff0c;其实都是差不多的…