• 方案介绍
  • 相关推荐
申请入驻 产业图谱

基于STM32的电子钟万年历闹钟OLED显示proteus仿真+实物设计(带温湿度显示)

01/04 21:15
661
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

 

基于STM32的电子钟万年历闹钟OLED显示设计

_带温湿度显示

本设计包含Proteus仿真+程序代码+原理图PCB+元器件清单+设计报告+讲解视频

一、开发环境

仿真图:proteus 8.17

程序编译器:keil 5

编程语言:C语言

设计编号:C0124

二、主要功能

基于STM32F103C8T6的多功能智能时钟系统

  1. 实时时钟显示:使用DS1302时钟芯片显示年、月、日、时、分、星期。

2.温湿度监测:DHT11传感器监测环境温湿度,温湿度数据显示。

温湿度超阈值黄灯亮。

3.闹钟功能:可以设置闹钟时间,具有开关闹钟选项,支持手动停止闹钟。

默认闹钟是00:01

4.具有时间设置功能:通过按键调整年月日时分秒,自动处理闰年,大小月。

5.使用0.96寸OLED显示屏显示所有信息。

主要硬件设备:STM32F103C8T6单片机、DHT11温湿度传感、OLED、蜂鸣器

资料下载链接(可点击):

链接: https://pan.baidu.com/s/1kHw9wHR0Rutz-lL5cVLVEA?pwd=9iq5

提取码: 9iq5

三、仿真设计

开始仿真后,OLED第一行显示年月日星期,第二行显示时分秒,第三行显示温度和湿度。如果温度或者湿度超过范围(温度15-30℃,湿度30-60%)指示灯黄灯亮。

img

闹钟时间到红色指示灯闪烁,蜂鸣器滴滴滴。

img

可以设置闹钟和年月日时分秒,通过OLED显示

img

四、程序设计

程序是用keil5 mdk版本打开的,如果打开有问题,核实下keil的版本,代码有注释方便理解。

img

img 代码

int main(void){		DHT11_Data_TypeDef DHT11_Data;//		delay_init();                 //延时函数 系统初始化//	Delay_Init(SYSTEM_CLOCK_8M);	User_Delay_Init();	LED_GPIO_Config();            //初始化GPIO接口		KEY_Init();                   //按键初始化		BEEP_Init();                  //蜂鸣器初始化	    GENERAL4_TIM_Init();          //10ms 通用定时器3初始化   10ms		NVIC_Configuration();	        //中断优先级设置			USART2_Config();		ds1302_gpio_init();delay_ms(5); //初始化ds1302端口	ds1032_init();	ds1032_read_realTime();    //读取此时时刻				OLED_Init();		            	//初始化OLED  	OLED_Clear();                 //清屏	delay_ms(100);					DHT11_Init();                 //传感器初始化				OLED_DrawBMP(0,0,128,8,BMP19);  //欢迎使用开机页面		delay_ms(1000);					OLED_Clear();                 //清屏			RealTime_Display_Init();        //上电初始化显示实时时间		UsartPrintf(USART_DEBUG, "RealTime_Display_Init...rn");    // 初始化时间变量为当前时间    UpdateTimeVariablesFromDS1302();    // 初始化星期显示    UpdateWeekDayDisplay();	while(1)					{  		    delay_ms(200);                 //添加延时,保证检测的稳定性						  ds1032_read_realTime();        //读取此时时刻        // 更新星期显示        if(TimeData.day != last_day) {            UpdateWeekDayDisplay();            last_day = TimeData.day;        }		RealTime_Display();            //实时时间日期实时刷新显示								if(DHT11_Data_Read_flag)       //6秒读取一次温湿度数据	 {	   	     if(DHT11_Read_TempAndHumidity ( & DHT11_Data ) == SUCCESS){			humidity = DHT11_Data.humi_int;			temperature = DHT11_Data.temp_int;		 }else{	 		UsartPrintf(USART_DEBUG, "ERROR:DHT11_Read_TempAndHumidity_faultrn");	 }		 DHT11_Data_Read_flag=0;              //复位读取DHT11数据标志	 }        // 闹钟报警程序段        if(Alarm_Clock && !Alarm_Manual_Stop_flag)         {            if((TimeData.hour == Alarm_Hour) && (TimeData.minute == Alarm_Minute)) {                Alarm_Clock_flag = 1;    // 闹钟报警标志位            } else {                Alarm_Clock_flag = 0;    // 闹钟报警标志位            }        } else {            Alarm_Clock_flag = 0;        // 闹钟报警标志位        }            // 闹钟报警过程中停止按键        if(!KEY_DEC) {            delay_ms(10);            if(KEY_DEC == 0) {                while(!KEY_DEC);	                Alarm_Manual_Stop_flag = 1;            }        }                        // 一旦设定值与当前时间不一致则手动终端报警复位        if(TimeData.minute != Alarm_Minute) {            Alarm_Manual_Stop_flag = 0;        }        // 按键修改时间和日期程序段        if(!KEY_ADJ) {            delay_ms(10);            if(KEY_ADJ == 0) {                while(!KEY_ADJ);                                // 关键修改:在进入时间设置前,更新时间为当前时间                UpdateTimeVariablesFromDS1302();                                OLED_Clear();               // 清屏                                    OLED_ShowChinese(0, 0, 21);   // 年			                OLED_ShowChinese(68, 0, 22);  // 月				                OLED_ShowChinese(0, 3, 23);   // 日                OLED_ShowChinese(68, 3, 24);  // 时                OLED_ShowChinese(0, 6, 25);   // 分                OLED_ShowChinese(68, 6, 26);  // 周(只显示,不可修改)                        Show_Modify_Data(num);        // 显示默认的时间日期设定参数                                    while(1) {                    // 在设置界面中也要实时更新星期显示                    u8 temp_w = CalculateWeekDay(y, m, d);                    OLED_ShowNum(88, 6, temp_w, 2, 16);                                    OLED_ShowNum(20, 0, y, 2, 16);                    OLED_ShowNum(88, 0, m, 2, 16);                    OLED_ShowNum(20, 3, d, 2, 16);                    OLED_ShowNum(88, 3, h, 2, 16);                    OLED_ShowNum(20, 6, mi, 2, 16);                                if(!KEY_ALM) {                        delay_ms(10);                        if(KEY_ALM == 0) {                            while(!KEY_ALM);		                             num++;                                                if(num > 4) num = 0; // 最大值为4,跳过星期选项                            Show_Modify_Data(num);                        }                    }                                            if(!KEY_ADD) {                        delay_ms(10);                        if(KEY_ADD == 0) {                            while(!KEY_ADD);		                            switch(num) {                                case 0:                                     y++;                                    if(y > 59) y = 0;  // 年循环:0-59                                    break;                                case 1:                                     m++;                                    if(m > 12) m = 1;  // 月循环:1-12                                    // 月份改变后,需要检查日期是否超出新月份的最大天数                                    if(d > GetMaxDaysInMonth(y, m)) {                                        d = GetMaxDaysInMonth(y, m);                                    }                                    break;                                case 2:                                     d++;                                    if(d > GetMaxDaysInMonth(y, m)) d = 1;  // 日循环:1-当月最大天数                                    break;                                case 3:                                     h++;                                    if(h > 23) h = 0;  // 时循环:0-23                                    break;                                case 4:                                     mi++;                                    if(mi > 59) mi = 0;  // 分循环:0-59                                    break;                            }                        }                    }                                                if(!KEY_DEC) {                        delay_ms(10);                        if(KEY_DEC == 0) {                            while(!KEY_DEC);		                            switch(num) {                                case 0:                                     if(y > 0) {                                        y--;                                    } else {                                        y = 59;  // 年循环:0-59                                    }                                    // 年份改变后,需要检查日期是否超出新年份二月的最大天数                                    if(m == 2 && d > GetMaxDaysInMonth(y, m)) {                                        d = GetMaxDaysInMonth(y, m);                                    }                                    break;                                case 1:                                     if(m > 1) {                                        m--;                                    } else {                                        m = 12;  // 月循环:1-12                                    }                                    // 月份改变后,需要检查日期是否超出新月份的最大天数                                    if(d > GetMaxDaysInMonth(y, m)) {                                        d = GetMaxDaysInMonth(y, m);                                    }                                    break;                                case 2:                                     if(d > 1) {                                        d--;                                    } else {                                        d = GetMaxDaysInMonth(y, m);  // 日循环:1-当月最大天数                                    }                                    break;                                case 3:                                     if(h > 0) {                                        h--;                                    } else {                                        h = 23;  // 时循环:0-23                                    }                                    break;                                case 4:                                     if(mi > 0) {                                        mi--;                                    } else {                                        mi = 59;  // 分循环:0-59                                    }                                    break;                            }                        }                    }                                                    if(!KEY_ADJ) {                        delay_ms(10);                        if(KEY_ADJ == 0) {                            while(!KEY_ADJ);                                                         // 设置时间时,使用计算得到的星期                            w = CalculateWeekDay(y, m, d);                            ProcessTimeSetting();  // 处理时间设置                            ds1302_write_time();  // 修改时间,写入                                                                OLED_Clear();         // 清屏                            ds1032_read_realTime(); // 读取此时时刻                            Modify_RealTime_Display(); // 修改后时间日期刷新一次显示                            break;                        }                    }                }            }		        }        // 修改闹钟时间和闹钟设定程序段        if(!KEY_ALM) {            delay_ms(10);            if(KEY_ALM == 0) {                while(!KEY_ALM);                OLED_Clear();               // 清屏                            OLED_ShowChinese(32, 0, 27);  // 闹钟设定                OLED_ShowChinese(48, 0, 28);                OLED_ShowChinese(64, 0, 29);                OLED_ShowChinese(80, 0, 30);                                    OLED_ShowChar(60, 3, ':', 16);                                    Show_Modify_Alarm(num2);        // 显示修改闹钟信息                                    while(1) {                    OLED_ShowNum(44, 3, Alarm_Hour, 2, 16);			                    OLED_ShowNum(68, 3, Alarm_Minute, 2, 16);	                                            // 闹钟开关显示                    if(Alarm_Clock) {                        OLED_ShowChinese(104, 3, 31);                    } else {                        OLED_ShowChinese(104, 3, 32);                    }                                        // 防止显示1位数,不整齐                    if(Alarm_Minute < 10) {                          OLED_ShowChar(68, 3, '0', 16);                    }                                        if(!KEY_ADJ) {                        delay_ms(10);                        if(KEY_ADJ == 0) {                            while(!KEY_ADJ);		                             num2++;                            if(num2 > 2) num2 = 0;                            Show_Modify_Alarm(num2);                        }	                    }                                        if(!KEY_ADD) {                        delay_ms(10);                        if(KEY_ADD == 0) {                            while(!KEY_ADD);		                            switch(num2) {                                case 0:                                     Alarm_Hour++;                                    if(Alarm_Hour > 23) Alarm_Hour = 0;  // 时循环:0-23                                    break;                                case 1:                                     Alarm_Minute++;                                    if(Alarm_Minute > 59) Alarm_Minute = 0;  // 分循环:0-59                                    break;                                case 2:                                     Alarm_Clock++;                                    if(Alarm_Clock > 1) Alarm_Clock = 0;  // 开关循环:0-1                                    break;                            }                        }                    }                                                if(!KEY_DEC) {                        delay_ms(10);                        if(KEY_DEC == 0) {                            while(!KEY_DEC);		                            switch(num2) {                                case 0:                                      if(Alarm_Hour > 0) {                                        Alarm_Hour--;                                    } else {                                        Alarm_Hour = 23;  // 时循环:0-23                                    }                                    break;                                case 1:                                     if(Alarm_Minute > 0) {                                        Alarm_Minute--;                                    } else {                                        Alarm_Minute = 59;  // 分循环:0-59                                    }                                    break;                                case 2:                                     if(Alarm_Clock > 0) {                                        Alarm_Clock--;                                    } else {                                        Alarm_Clock = 1;  // 开关循环:0-1                                    }                                    break;                            }                        }                    }                                        if(!KEY_ALM) {                        delay_ms(10);                        if(KEY_ALM == 0) {                            while(!KEY_ALM);                            OLED_Clear();                            ds1032_read_realTime();        // 读取此时时刻                            Modify_RealTime_Display();    // 修改后时间日期刷新一次显示                            break;                        }                    }																		 							 						 					}											}		}	//*

五、原理图PCB

img

img

img

六、元器件清单

1 1 BS-02-A1AJ010 B1
2 1 2.3kHz BUZ1
3 1 1N4007 D1
4 4 K4-6×6_TH KEY1,KEY2,KEY3,KEY4
5 1 LED-TH-3mm_R LED2
6 1 XL-302UYD LED3
7 1 0.96OLED模块_4P OLED
8 1 SS8550 Q1
9 1 4K7 R1
10 2 100 R3,R7
11 1 1k R5
12 1 10k R6
13 1 DHT11 S1
14 1 DS1302ZN U2
15 1 LCKFB-DKX-STM32F103C8T6 U6
16 1 32.768KHZ X1

七、实物图

img

img

八、设计报告

6541字设计报告,内容包括硬件设计、软件设计、调试、结论等。

报告

随着物联网技术智能家居的快速发展,传统时钟已不能满足现代生活需求。智能时钟作为智能家居系统的重要组成部分,不仅需要提供准确的时间信息,还应具备环境监测、智能提醒等扩展功能。STM32微控制器以其高性能、低功耗和丰富的外设接口,成为开发此类嵌入式系统的理想选择。

尤为值得关注的是,本设计经过了严格的验证流程,利用Proteus仿真软件进行了全面的功能测试与稳定性评估。通过仿真,设计团队不仅提前发现并修正了潜在的硬件冲突与软件逻辑错误,还对系统的实际工作性能进行了细致的校验,确保了最终实物制作与应用时的高可靠性和稳定性。这一仿真验证过程的加入,不仅提升了设计的科学严谨性,也为后续的优化迭代提供了宝贵的参考依据。

九、资料清单&下载链接

img

0、常见使用问题及解决方法–必读!!!!

1、程序代码

2、Proteus仿真

3、功能要求

4、开题报告

5、设计报告

6、讲解视频

7、原理图PCB

8、元器件清单

9、实物图

10、相关框图

Altium Designer 安装破解

filename.bat

KEIL+proteus 单片机仿真设计教程

KEIL安装破解

Proteus元器件查找

Proteus安装

Proteus简易使用教程

单片机学习资料

相关数据手册

答辩技巧

设计报告常用描述

鼠标双击打开查找嘉盛单片机51 STM32单片机课程毕业设计.url

资料下载链接(可点击):

链接: https://pan.baidu.com/s/1kHw9wHR0Rutz-lL5cVLVEA?pwd=9iq5

提取码: 9iq5

相关推荐