基于STM32单片机的智能家居窗户窗帘控制系统红外遥控proteus仿真原理图PCB

2023-05-16

功能:
0.本系统采用STM32F103RCT6作为单片机
1.LCD1602液晶实时显示当前时间/窗帘状态/光照强度
2.支持手动按键/定时/光强检测三种模式控制窗帘
3.'设置’键进入设置界面
4.默认状态下’确定’键可切换模式
5.设置界面’确定’为确定
6.支持掉电保存
7.采用DC002作为电源接口可直接输入5V给整个系统供电

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

PCB :
在这里插入图片描述

主程序:

/*************************************************************
                        智能窗帘

补充说明:
***************************************************************/
#include "reg52.h"
#include "LCD1602.h"
#include "DS1302.h"
#include "28BYJ48.h"
#include "eeprom52.h"
#include "tlc0832.h"
#include "infrared.h"
#include "delay.h"

#define uchar unsigned char //宏定义
#define uint unsigned int

/*******************引脚定义*********************/
sbit KEY_MODE    = P3^3;   //设置键
sbit KEY_ADD     = P3^4;   //加值键
sbit KEY_SUB     = P3^6;   //减值键
sbit KEY_ENTER   = P3^5;   //确定键
sbit BUZZER      = P2^0;   //蜂鸣器

sbit SW1      = P1^3;   //全开 限位开关
/*******************变量定义*********************/
uchar light_up = 80;
uchar light_down = 30; //存储光强上、下限值
uchar set_f = 0;            //设置选择标记,=0非设置,=1设置年,=2设置月,=3设置日,=4设置时,=5设置分,=6设置秒
                            //              =7设置定时-时,=8设置定时-分,=9设置定时-开关,=10设置窗帘打开/关闭
                            //				=11设置光强上限,=12设置光强下限,=13设置校准窗帘位置

unsigned char dis[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
uchar num;   //计数变量
uchar ds[4] = {8, 30, 16, 20}; //定时控制开时、分、控制关时、分

uchar mode = 0; //模式标记。=0手动,=1定时,=2光控
uchar light;    //存储光强

uint moto_num = 0;                                        //记录窗帘位置
uchar motor_state = 0;                                     //窗帘状态,=0已经关闭,=1处于运转过程中,=2已经打开
bit moto_f = 0;                                           //标记当前控制状态,=0控制关,=1控制开
uchar code display_mode[3][3] = {"SD\0", "DS\0", "GK\0"}; //显示模式

void WriteData(void)
{
    SectorErase(0x2000);    //擦除扇区
    WriteByte(0x2000, ds[0]);  //写入【定时时间】数据保存
    WriteByte(0x2001, ds[1]); //写入【定时时间】数据保存存
    WriteByte(0x2002, ds[2]); //写入【定时时间】数据保存存
    WriteByte(0x2003, ds[3]); //写入【定时时间】数据保存存
    WriteByte(0x2004, light_up); //写入【光强上限值】数据保存
    WriteByte(0x2005, light_down); //写入【光强下限值】数据保存
    WriteByte(0x2006, mode); //写入【模式】数据保存
}

void ReadData(void)
{
    ds[0] = ReadByte(0x2000);      //读取存储的【定时时间】数据
    ds[1] = ReadByte(0x2001);      //读取存储的【定时时间】数据
    ds[2] = ReadByte(0x2002);      //读取存储的【定时时间】数据
    ds[3] = ReadByte(0x2003);      //读取存储的【定时时间】数据
    light_up = ReadByte(0x2004);   //读取存储的【光强上限值】数据
    light_down = ReadByte(0x2005); //读取存储的【光强下限值】数据
    mode = ReadByte(0x2006);       //读取存储的【模式】数据
}

/********************************************************
函数名称:void display(void)
函数作用:正常显示日期、时间、光强等函数
参数说明:
********************************************************/
void display(void)
{
    uint t[3];

    //显示时间
    LCD_DispOneChar(0, 1, dis[time[2] / 10]); //显示时【0:表示第1列,2:表示第2行,所有关于显示都一样】
    LCD_DispOneChar(1, 1, dis[time[2] % 10]);
    LCD_DispOneChar(2, 1, ':');
    LCD_DispOneChar(3, 1, dis[time[1] / 10]); //显示分【3:表示第4列,2:表示第2行,所有关于显示都一样】
    LCD_DispOneChar(4, 1, dis[time[1] % 10]);
    LCD_DispOneChar(5, 1, ':');
    LCD_DispOneChar(6, 1, dis[time[0] / 10]); //显示秒
    LCD_DispOneChar(7, 1, dis[time[0] % 10]);

    //显示日期
    LCD_DispOneChar(0, 0, dis[time[6] / 10]); //显示年
    LCD_DispOneChar(1, 0, dis[time[6] % 10]);
    LCD_DispOneChar(2, 0, '/');
    LCD_DispOneChar(3, 0, dis[time[4] / 10]); //显示月
    LCD_DispOneChar(4, 0, dis[time[4] % 10]);
    LCD_DispOneChar(5, 0, '/');
    LCD_DispOneChar(6, 0, dis[time[3] / 10]); //显示日
    LCD_DispOneChar(7, 0, dis[time[3] % 10]);

    //显示模式
    LCD_DispStr(9, 0, display_mode[mode]);

    //显示光强
    if (light > 99)
        LCD_DispOneChar(12, 0, dis[light / 100]);
    else
        LCD_DispOneChar(12, 0, ' ');
    LCD_DispOneChar(13, 0, dis[light % 100 / 10]);
    LCD_DispOneChar(14, 0, dis[light % 10]);
    LCD_DispOneChar(15, 0, '%');

    //光强控制
    if (mode == 2) //光控模式
    {
        if ((light >= light_up || light < light_down)) //判断实际光强是否【大于等于上限 或 小于下限值】、当前处于打开状态
        {
            moto_f = 0;     //标记当前控制窗帘关闭
            motor_state = 1; //标记窗帘处于运转过程中
        }
        else if ((light < light_up && light >= light_down)) //判断实际光强是否【大于等于下限值 并且 小于上限】、当前处于关闭状态
        {
            moto_f = 1;     //标记当前控制窗帘打开
            motor_state = 1; //标记窗帘处于运转过程中
        }
    }
    else if (mode == 1) //定时模式
    {
        t[0] = time[2] * 60 + time[1]; //当前时间
        t[1] = ds[0] * 60 + ds[1];     //窗帘开启时间点
        t[2] = ds[2] * 60 + ds[3];     //窗帘关闭时间点

        if (t[1] < t[2]) //0时 --> t[1] --> t[2] --> 24时
        {
            if (t[0] >= t[1] && t[0] <= t[2])
                moto_f = 1; //标记当前需要打开窗帘
            else
                moto_f = 0; //标记当前需要关闭窗帘
        }
        else //0时 --> t[2] --> t[1] --> 24时
        {
            if (t[0] >= t[1] || t[0] <= t[2])
                moto_f = 1; //标记当前需要打开窗帘
            else
                moto_f = 0; //标记当前需要关闭窗帘
        }
        motor_state = 1; //标记窗帘处于运转过程中
    }

    if (moto_f == 0 && motor_state != 0 && SW1 != 0) //控制关闭窗帘
    {
        if (moto_num == 0) //控制次数减到0时,表示窗户已经关闭完成
        {
            BYJ48 = BYJ48 & 0xf0; //关闭步进电机
            motor_state = 0;    //标记窗帘处于关闭状态
            LCD_DispStr(10, 1, "ZT:OFF");
        }
        else
        {
            motor_z();  //步进电机正转
            moto_num--; //控制次数-1
            LCD_DispStr(10, 1, "-->OFF");
        }
    }
    else if (moto_f == 1 && motor_state != 2 && SW1 != 0) //控制打开窗帘
    {
        if (moto_num >= 192) //控制次数加到192时,表示窗户已经打开完成
        {
            BYJ48 = BYJ48 & 0xf0; //关闭步进电机
            motor_state = 2;    //标记窗帘处于打开状态
            LCD_DispStr(10, 1, "ZT:ON ");
        }
        else
        {
            motor_f();  //步进电机反转
            moto_num++; //控制次数+1
            LCD_DispStr(10, 1, "-->ON ");
        }
    }
    else //窗户处于停止状态
    {
        BYJ48 = BYJ48 & 0xf0; //关闭步进电机
        if (motor_state == 0)
            LCD_DispStr(10, 1, "ZT:OFF");
        else if (motor_state == 2)
            LCD_DispStr(10, 1, "ZT:ON ");
    }
}
/********************************************************
函数名称:void display2(void)
函数作用:显示调整日期、时间函数
参数说明:
********************************************************/
void display2()
{
    num++;

    LCD_DispStr(1, 0, "Date:");
    LCD_DispStr(1, 1, "Time:");

    if (num % 2 == 0) //偶数次显示,奇数次不显示。这样就会有闪烁效果,可以清楚看到当前设置的是哪个值
    {
        LCD_DispOneChar(6, 0, dis[time[6] / 10]); //显示年
        LCD_DispOneChar(7, 0, dis[time[6] % 10]);
        LCD_DispOneChar(8, 0, '/');
        LCD_DispOneChar(9, 0, dis[time[4] / 10]); //显示月
        LCD_DispOneChar(10, 0, dis[time[4] % 10]);
        LCD_DispOneChar(11, 0, '/');
        LCD_DispOneChar(12, 0, dis[time[3] / 10]); //显示日
        LCD_DispOneChar(13, 0, dis[time[3] % 10]);

        LCD_DispOneChar(6, 1, dis[time[2] / 10]); //显示时
        LCD_DispOneChar(7, 1, dis[time[2] % 10]);
        LCD_DispOneChar(8, 1, ':');
        LCD_DispOneChar(9, 1, dis[time[1] / 10]); //显示分
        LCD_DispOneChar(10, 1, dis[time[1] % 10]);
        LCD_DispOneChar(11, 1, ':');
        LCD_DispOneChar(12, 1, dis[time[0] / 10]); //显示秒
        LCD_DispOneChar(13, 1, dis[time[0] % 10]);
    }
    else //奇数次不显示
    {
        switch (set_f) //根据当前设置的内容,对应位置闪烁
        {
        case 1:
            LCD_DispStr(6, 0, "  ");
            break;
        case 2:
            LCD_DispStr(9, 0, "  ");
            break;
        case 3:
            LCD_DispStr(12, 0, "  ");
            break;
        case 4:
            LCD_DispStr(6, 1, "  ");
            break;
        case 5:
            LCD_DispStr(9, 1, "  ");
            break;
        case 6:
            LCD_DispStr(12, 1, "  ");
            break;
        default:
            break;
        }
    }
}
/********************************************************
函数名称:void display3(void)
函数作用:显示调整定时时间函数
参数说明:
********************************************************/
void display3()
{
    num++;
    LCD_DispStr(0, 0, "Sets timer time:");
    LCD_DispStr(7, 1, "--");
    if (num % 2 == 0) //偶数次显示,奇数次不显示。这样就会有闪烁效果,可以清楚看到当前设置的是哪个值
    {
        LCD_DispOneChar(1, 1, dis[ds[0] / 10]); //显示定时开-时
        LCD_DispOneChar(2, 1, dis[ds[0] % 10]);
        LCD_DispOneChar(3, 1, ':');
        LCD_DispOneChar(4, 1, dis[ds[1] / 10]); //显示定时开-分
        LCD_DispOneChar(5, 1, dis[ds[1] % 10]);

        LCD_DispOneChar(10, 1, dis[ds[2] / 10]); //显示定时关-时
        LCD_DispOneChar(11, 1, dis[ds[2] % 10]);
        LCD_DispOneChar(12, 1, ':');
        LCD_DispOneChar(13, 1, dis[ds[3] / 10]); //显示定时关-分
        LCD_DispOneChar(14, 1, dis[ds[3] % 10]);
    }
    else //奇数次不显示
    {
        switch (set_f) //根据当前设置的内容,对应位置闪烁
        {
        case 7:
            LCD_DispStr(1, 1, "  ");
            break;
        case 8:
            LCD_DispStr(4, 1, "  ");
            break;
        case 9:
            LCD_DispStr(10, 1, "  ");
            break;
        case 10:
            LCD_DispStr(13, 1, "  ");
            break;
        default:
            break;
        }
    }
}
/********************************************************
函数名称:void display4(void)
函数作用:显示调整光强控制函数
参数说明:
********************************************************/
void display4(void)
{
    num++;

    LCD_DispStr(0, 0, "Light_Up  :");
    LCD_DispStr(0, 1, "Light_Down:");
    LCD_DispOneChar(15, 0, '%');
    LCD_DispOneChar(15, 1, '%');
    if (num % 2 == 0) //偶数次显示,奇数次不显示。这样就会有闪烁效果,可以清楚看到当前设置的是哪个值
    {
        LCD_DispOneChar(12, 0, dis[light_up / 100]); //显示光强上限值
        LCD_DispOneChar(13, 0, dis[light_up % 100 / 10]);
        LCD_DispOneChar(14, 0, dis[light_up % 10]);

        LCD_DispOneChar(12, 1, dis[light_down / 100]); //显示光强下限值
        LCD_DispOneChar(13, 1, dis[light_down % 100 / 10]);
        LCD_DispOneChar(14, 1, dis[light_down % 10]);
    }
    else //奇数次不显示
    {
        switch (set_f) //根据当前设置的内容,对应位置闪烁
        {
        case 11:
            LCD_DispStr(12, 0, "   ");
            break;
        case 12:
            LCD_DispStr(12, 1, "   ");
            break;
        default:
            break;
        }
    }
}
/********************************************************
函数名称:void KeyScan(void)
函数作用:按键查询处理函数
参数说明:
********************************************************/
void KeyScan(void)
{
    //设置键
    if (hw_data == 'B' || KEY_MODE == 0) //按键按下
    {
        DelayMs(50);                        //延时消抖
        if (hw_data == 'B' || KEY_MODE == 0) //再次确认按键按下
        {
            BUZZER = 0;
            DelayMs(130);
            BUZZER = 1;
            BYJ48 = BYJ48 & 0xf0; //关闭步进电机
            if (set_f == 6)    //日期、时间校准完
            {
                LCD_Clear(); //清除屏幕显示
                DelayMs(4);;        //延时等待全部清除完毕
                set_f = 13;              //跳到校准窗帘状态
            }
            else if (set_f == 0) //进入设置先清除屏幕,显示设置部分
            {
                Write_DS1302(WRITE_PROTECT, 0X00); //禁止DS1302写保护
                LCD_Clear();          //清除屏幕显示
                DelayMs(4);;                 //延时等待全部清除完毕
                switch (mode)                     //根据对应的模式,设置对应的参数
                {
                case 0:
                    set_f = 1;
                    break; //手动模式
                case 1:
                    set_f = 7;
                    break; //定时模式
                case 2:
                    set_f = 11;
                    break; //光控模式
                default:
                    break;
                }
            }
            else if (set_f == 10 || set_f == 12) //进入设置日期时间
            {
                LCD_Clear(); //清除屏幕显示
                DelayMs(4);;        //延时等待全部清除完毕
                set_f = 1;               //进入校准时间
            }
            else
                set_f++; //设置变量+1
            if (set_f > 12)
            {
                set_f = 0; //重置设置变量

                Write_DS1302(WRITE_MINUTE, (time[1] / 10) * 16 + time[1] % 10); //将设置好的时间写入DS1302
                Write_DS1302(WRITE_SECOND, (time[0] / 10) * 16 + time[0] % 10);

                WriteData();

                LCD_Clear(); //清除屏幕显示
                DelayMs(4);;        //延时等待全部清除完毕
            }
        }
        while (!KEY_MODE)
            ; //等待按键松开
    }
    //确定
    if (hw_data == '|' || KEY_ENTER == 0) //按键按下
    {
        DelayMs(50);                                        //延时消抖
        if ((hw_data == '|' || KEY_ENTER == 0) && set_f != 0) //再次确认按键按下
        {
            BUZZER = 0;
            DelayMs(130);
            BUZZER = 1;
            if (set_f < 7)
            {
                Write_DS1302(WRITE_MINUTE, (time[1] / 10) * 16 + time[1] % 10); //将设置好的时间写入DS1302
                Write_DS1302(WRITE_SECOND, (time[0] / 10) * 16 + time[0] % 10);
            }
            set_f = 0; //重置设置变量

            WriteData();

            LCD_Clear(); //清除屏幕显示
            DelayMs(4);;        //延时等待全部清除完毕
        }
        else if (KEY_ENTER == 0 && set_f == 0) //切换模式
        {
            mode++;              //模式变量+1
            if (mode >= 3)       //最大3个模式
                mode = 0;        //重新回到第1个模式
            if (motor_state == 1) //如果处于运转过程中
            {
                if (moto_f == 0) //控制步进电机关闭
                    motor_state = 0;
                else //控制步进电机打开
                    motor_state = 2;
            }
            WriteData();
        }
        while (!KEY_ENTER)
            ; //等待按键松开
    } 作者:极寒钛科技 https://www.bilibili.com/read/cv20281890 出处:bilibili

实物演示视频:
https://www.bilibili.com/video/BV1PV4y1L7nH/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于STM32单片机的智能家居窗户窗帘控制系统红外遥控proteus仿真原理图PCB 的相关文章

随机推荐

  • C++(11):bind

    bind函数可以将既有函数的参数绑定起来 从而生成一个函数对象 include lt iostream gt include lt functional gt using namespace std void func1 int d cou
  • Linux编程:time/gettimeofday获取时间戳

    时间戳 指格林威治时间从1970年1月1日 00 00 00 GMT 至当前时间的总秒数 需要注意的是 时间戳跟时区没有关系 不论在哪个时区 时间戳是一个值 linux下获得时间戳常用的的方式有两个 1 通过time函数 include l
  • Ubuntu(20.04):安装VNC

    1 首先安装tightvncserver nbsp sudo apt install tightvncserver 2 安装gnome panel 否则vnc后的画面是纯灰色 sudo apt nbsp install gnome pane
  • nlohmann json:struct与json的互转

    nlohmann json可以很方便的实现struct与json的互转 对于化定义结构体成员时有就地初始的情况 include lt iostream gt include lt string gt include lt nlohmann
  • C++(11):mem_fn,将类的成员函数转换为函数对象

    C 43 43 11 提供了mem fn xff0c 类似于std function xff0c 用于将类的成员函数转换为函数对象 xff1a include lt functional gt include lt iostream gt
  • C++(20):span防止数组越界

    C C 43 43 一直都有数组越界这个陷阱 xff0c 越界后容易造成数据不一致 xff0c 程序运行状态混乱 xff0c coredump C 43 43 20提供了span容器 xff0c 他用于表示一段连续的内存空间 xff0c 并
  • gcc:升级编译器版本

    Ubuntu 22 04 下升级gcc和g 的方法 1 添加工具链 sudo add apt repository ppa ubuntu toolchain r test nbsp 2 更新apt软件列表 sudo apt update 3
  • JAVA: String转JsonArray

    String str 61 34 34 JsonArray jsonArray 61 new JsonParser parse str getAsJsonArray JsonObject jsonObject 61 jsonArray ge
  • CPU性能天梯图

    查看更多榜单 gt gt 查看桌面CPU性能榜 二代酷睿三代酷睿四代酷睿五六代酷睿七代酷睿八代酷睿九代酷睿十代酷睿三代锐龙二代锐龙一代锐龙八代APU七代APU旧APU推土机 打桩机弈龙 速龙 线程撕裂者3990X 线程撕裂者3970X 线程
  • Ubuntu必备开发工具安装

    1 安装gcc g 43 43 gdb make 等基本编程工具 sudo apt get install build essential 2 安装常见开发工具 sudo apt get install autoconf automake
  • apt与apt-get区别

    apt包含了apt get apt cache apt config xff0c 属于包含与被包含关系 apt与apt get命令区别如下 xff1a
  • Java super关键字:super调用父类的构造方法、利用super访问父类成员

    由于子类不能继承父类的构造方法 xff0c 因此 xff0c 要调用父类的构造方法 xff0c 必须在子类的构造方法体的第一行使用 super 方法 该方法会调用父类相应的构造方法来完成子类对象的初始化工作 在以下情况下需要使用 super
  • 如何将ova转成vmdk文件

    ova是一个压缩文件 xff0c 使用7zip打开ova文件可以看到 xff0c 里面有三个文件组成 xff1a ovf 是一个XML描述符 xff0c 定义了虚拟机的元数据信息 xff0c 如名称 硬件要求 xff0c 并且包含了OVF文
  • 基于51单片机的温室大棚土壤湿度检测智能语音灌溉通风系统proteus仿真原理图PCB

    功能介绍 xff1a 0 本系统采用STC89C52作为单片机 1 系统实时监测当前的土壤湿度和空气温湿度 xff0c 并上传WIFI 2 支持手动 自动两种模式 3 自动模式下 xff0c 当温湿度超过阈值上限时 xff0c 打开通风机
  • 基于51单片机的自动窗户控制系统风速测量proteus仿真原理图PCB

    功能介绍 xff1a 0 本系统采用STC89C52作为单片机 1 系统实时监测当前的雨滴 温湿度 风速 xff0c 烟雾浓度 2 支持手动 自动两种模式 3 自动模式下 窗户关闭状态下 xff0c 当烟雾浓度超过阈值 xff0c 打开窗户
  • 基于51单片机的智能路灯控制系统proteus仿真原理图PCB

    功能 xff1a 0 本系统采用STC89C52作为单片机 1 LCD1602液晶实时显示当前时间 环境光强 工作模式 2 支持路灯故障检测 3 工作时间内 17 24时 xff0c 两个路灯同时点亮 xff0c 24时以后 xff0c B
  • 基于51单片机的温度控制系统数码管显示蜂鸣器报警proteus仿真原理图PCB

    功能 xff1a 0 本系统采用STC89C52作为单片机 1 系统实时监测并显示当前温度 xff0c 并通过四位数码管显示 2 超过设定阈值 xff0c 蜂鸣器将报警 xff0c 同时控制相应继电器实现降温或者加热 3 系统具备三个功能按
  • 基于STM32单片机的智能水表水流量计原理图PCB

    功能 xff1a 0 本系统采用STM32F103C8T6作为单片机 1 该系统采用LCD1602液晶显示各种参数 xff0c 包括瞬时流量速度 xff0c 已经总流量 xff0c 同时可通过按键设置最大阈值 xff0c 一旦流量超过该值将
  • ProtoBuf: ByteString和String转换

    ByteString bs 61 ByteString copyFrom 34 hi 34 getBytes System out println bs toStringUtf8
  • 基于STM32单片机的智能家居窗户窗帘控制系统红外遥控proteus仿真原理图PCB

    功能 xff1a 0 本系统采用STM32F103RCT6作为单片机 1 LCD1602液晶实时显示当前时间 窗帘状态 光照强度 2 支持手动按键 定时 光强检测三种模式控制窗帘 3 39 设置 键进入设置界面 4 默认状态下 确定 键可切