600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 基于STM32单片机的智能家居窗户窗帘控制系统红外遥控proteus仿真原理图PCB

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

时间:2023-01-02 18:15:50

相关推荐

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

功能:

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(0x, ds[3]); //写入【定时时间】数据保存存WriteByte(0x, light_up); //写入【光强上限值】数据保存WriteByte(0x, light_down); //写入【光强下限值】数据保存WriteByte(0x, mode); //写入【模式】数据保存}void ReadData(void){ds[0] = ReadByte(0x2000);//读取存储的【定时时间】数据ds[1] = ReadByte(0x2001);//读取存储的【定时时间】数据ds[2] = ReadByte(0x2002);//读取存储的【定时时间】数据ds[3] = ReadByte(0x);//读取存储的【定时时间】数据light_up = ReadByte(0x); //读取存储的【光强上限值】数据light_down = ReadByte(0x); //读取存储的【光强下限值】数据mode = ReadByte(0x); //读取存储的【模式】数据}/********************************************************函数名称: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]);elseLCD_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; //标记当前需要打开窗帘elsemoto_f = 0; //标记当前需要关闭窗帘}else //0时 --> t[2] --> t[1] --> 24时{if (t[0] >= t[1] || t[0] <= t[2])moto_f = 1; //标记当前需要打开窗帘elsemoto_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--; //控制次数-1LCD_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++; //控制次数+1LCD_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;//进入校准时间}elseset_f++; //设置变量+1if (set_f > 12){set_f = 0; //重置设置变量Write_DS1302(WRITE_MINUTE, (time[1] / 10) * 16 + time[1] % 10); //将设置好的时间写入DS1302Write_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); //将设置好的时间写入DS1302Write_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++; //模式变量+1if (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); //等待按键松开} 作者:极寒钛科技 /read/cv20281890 出处:bilibili

实物演示视频:

/video/BV1PV4y1L7nH/

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。