多功能数字时钟(STC15)

目录

一、任务书确定

二、进度表

三、原理框图、原理图、PCB

 四、简要程序流程图

五、 部分程序

5.1、主函数

5.2、菜单部分

六、实物、功能展示

七、源码+其它资料


一、任务书确定

1、蓝牙控制OLED12864显示2级菜单界面

2、按键控制MCU进入掉电模式,外部中断唤醒

3、按键切换主界面字体大小

4、通过蓝牙模块设置时间、1个闹钟

二、进度表

起止时间

任务简述

Start

耗时(天)

2021.10.20

2

1.1、确定选题+任务书

2021.10.23

7

1.2、绘制原理图、PCB

1.3、华秋、淘宝采购元器件

2021.11.3

5

1.4、嘉立创打板、检查样板(结果:封装错误)

2021.11.9

2

1.5、修改原理图、PCB

2021.11.10

5

1.6、捷配打样板

2021.11.16

2

1.7、检查+焊接样板

2021.11.18

2

1.8、调试+检查PCB(结果:没问题)

2021.11.30

3

1.9、在原有基础上改善PCB(减少飞线)

2021.11.20

1

2.0、LCD1602显示模块测试

2021.12.2

2

2.1、OLED12864模块显示测试

2021.12.4

3

2.2、OLED12864初始化界面+显示基本时钟功能

2021.12.8

1

2.3、蓝牙模块测试

2021.12.9

~

2021.12.17

9

2.4.1、DS18B20温度测量并显示

2.4.2、蓝牙控制OLED12864显示2级菜单界面

2.4.3、按键关机、开机

2.4.4、按键切换主界面字体大小

2.4.5、蓝牙控制显示2级菜单并设置时间、1个闹钟

三、原理框图、原理图、PCB

 

 四、简要程序流程图

五、 部分程序

5.1、主函数

#include "main.h"
#include "timing.h"
#include "Bluetooth.h"
#include "Menu.h"
#include "Keyscan.h"


bit MODE = 0;	// 全局变量,控制显示字体大小(0:32 or 1:48)


/**
	*	@brief	:	主函数
	*	@param	:	
	*	@retval	:	
	*/
void main(void)
{	
	OPEN_Init();
	while(1)
	{
		Menu_Proc(Uart2_RecByte());
		T1_Proc();
		Keyscan();
	}
}

5.2、菜单部分

#ifndef __MAIN_H
#define __MAIN_H

#include <STC15F2K60S2.H>

typedef unsigned int 				uint32;
typedef unsigned short int 	uint16;
typedef unsigned char 			uint8;


extern bit MODE;


// 晶振频率
#define SYSCLK									11059200UL
//-------------OLED12864 字符位置信息------------
#define SIZE(MODE)					(MODE) ? 48 : 32	// 字体大小(MODE: 0:32 1:48)
// 日期	显示大小、位置
#define DA_SZ(MODE)					(MODE) ? 8  : 16
#define DA_POS(MODE)				(MODE) ? 34 : 24
// 时间 显示 位置
#define T_WIDE(MODE)				(MODE) ? 24 : 16
#define T_POSX(MODE)				(MODE) ? 4  : 24
#define T_POSY(MODE)				(MODE) ? 1  : 2
#define C_POSX(MODE)				(MODE) ? 52 : 56	// T_POSX(MODE) + (字宽度*2)
#define MIN_POSX						(MODE) ? 76 : 72	// CHAR_POSX(MODE) + 字符宽度	(':'的位置)
// 菜单字符显示信息
#define MENU_POSY(MODE)			(MODE) ? 7	:	6



//-------------LED、按键引脚定义------------
sbit LED_RED = P3^5;		// 低电平点亮
sbit LED_GREEN = P4^5;
sbit SPEAKER = P1^1;






#endif

#ifndef __MENU_H
#define __MENU_H

#include "main.h"


extern uint8 Clocking[2];		// 0:时 1:分
extern bit CLOCK_FLAG;


void OPEN_Init(void);
void Show_Info(void);
void Menu_Proc(uint8 dat);
bit Set_Time(void);
bit Set_Clock(void);
bit SetDate(uint8 set_mode);
void Clock_Check(uint8 Min_Dat);




#endif

#include "Menu.h"
#include "oled.h"
#include "bmp.h"
#include "Bluetooth.h"
#include "ds1302.h"
#include "ds18b20.h"
#include "Keyscan.h"
#include "timing.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"


static uint8 Clocking[2];		// 0:时 1:分
bit CLOCK_FLAG = 0;

/**
	*	@brief	:	多功能电子时钟初始化
	*	@param	:	
	*	@retval	:	
	*/
void OPEN_Init(void)
{
	
	LED_RED = 1;
	LED_GREEN = 1;
	
	//RTC_Set(RTC_Dat);			// 设置默认时钟
	
	OLED_Init();						// 初始化 OLED12864
	OLED_ColorTurn(0);			// 0正常显示,1 反色显示
  OLED_DisplayTurn(0);		// 0正常显示 1 屏幕翻转显示
	
	OLED_DrawBMP(0, 0, 128, 64, BMP1);	// 显示图片
	delay_ms(300);
	
	Show_Info();
	INTx_Init();						// 外部中断初始化
	T1_Init();							// 初始化定时器,应放在OLED初始化之后	
	Bluetooth_Init();				// 初始化蓝牙串口
}


/**
	*	@brief	:	显示信息
	*	@param	:	
	*	@retval	:	
	*/
void Show_Info(void)
{
	uint8 Buf[11];

	OLED_Clear();					// 清屏
	RTC_Read(RTC_Dat);			// 读时间
	RTC_Dat[0] = Read_Ds1302_Byte(RTC_Addr_R_Year);				// 读 年
	sprintf(Buf, "20%02x.%02x.%02x", \
					(uint32)RTC_Dat[0], 		 \
					(uint32)RTC_Dat[2], 		 \
					(uint32)RTC_Dat[3]);
	OLED_ShowString(DA_POS(MODE), 0, Buf, DA_SZ(MODE));		
	//	显示初始时间
	sprintf(Buf, "%02x:%02x", 			 \
					(uint32)RTC_Dat[4], 		 \
					(uint32)RTC_Dat[5]);
	OLED_ShowStr32or48(T_POSX(MODE), T_POSY(MODE), Buf, SIZE(MODE));	
	
	OLED_ShowString(0, MENU_POSY(MODE), "Menu", DA_SZ(MODE));
	sprintf(Buf, "%5.1f", (float)rd_temperature());
	OLED_ShowString(80, MENU_POSY(MODE), Buf, DA_SZ(MODE));		// 显示温度
}




/**
	*	@brief	:	功能菜单页面处理
	*	@param	:	
	*	@retval	:	
	*/
void Menu_Proc(uint8 dat)
{
	if(dat == '0')
	{
		ET1 = 0;				// 关 T1 中断
		OLED_ShowMenu();
		Uart2_SendStr("\r\n菜单界面\r\n");
		while(1)
		{
			if((dat=Uart2_RecByte()) == '0')
			{
				Uart2_SendStr("Return\r\n");
				Show_Info();
				ET1 = 1;		// 开 T1 中断
				return;
			}
			else
			{
				switch(dat)
				{
					case '1': 
						if(Set_Time() == 1) 
						{
							Show_Info();
							Uart2_SendStr("\r\n时间设置成功\r\n");
							ET1 = 1;
							return; 
						}
						else
						{
							Show_Info();
							Uart2_SendStr("\r\n时间设置失败\r\n");
							ET1 = 1;
							return; 
						}
						break;
					case '2':	
						if(Set_Clock() == 1) 
						{
							Show_Info();
							Uart2_SendStr("\r\n闹钟设置成功\r\n");
							ET1 = 1;
							return; 
						}
						else
						{
							Show_Info();
							Uart2_SendStr("\r\n闹钟设置失败\r\n");
							ET1 = 1;
							return;
						}
						break;
				}
			}
		}
	}
}



/**
	*	@brief	:	设置时间
	*	@param	:	
	*	@retval	:	
	*/
bit Set_Time(void)
{
	uint8 i = 0, ch;
	
	OLED_Clear();
	for(i=0; i<4; i++)									// 显示:设置时间
		OLED_ShowChinese((32+i*16), 0, (2+i), 16);
	
	Uart2_SendStr("\r\n请设置时间\r\n");
	if(SetDate(0) == 1)									// 设置年月日成功
	{
		Uart2_SendStr("\r\n是(1)否(0)继续设置时间?\r\n");
		while(1)
		{
			ch=Uart2_RecByte();
			if(ch == '0')
				break;
			else if(ch == '1')
			{
				if(SetDate(1)==0)		// 设置时分
					return 0;
				else
					return 1;
			}
		}
		return 1;
	}
	else
		return 0;
}





/**
	*	@brief	:	设置闹钟
	*	@param	:	
	*	@retval	:	
	*/
bit Set_Clock(void)
{
	uint8 i;
	
	OLED_Clear();
	for(i=0; i<2; i++)								// 设置
		OLED_ShowChinese((32+i*16), 0, (2+i), 16);		
	for(i=0; i<2; i++)								// 闹钟
		OLED_ShowChinese((64+i*16), 0, (6+i), 16);
	
	if(SetDate(2) == 1)	// 设置闹钟成功
	{
		CLOCK_FLAG = 1;		// 有闹钟
		return 1;
	}
	else
	{
		CLOCK_FLAG = 0;		// 无闹钟
		return 0;
	}
}



/**
	*	@brief	:	设置年月日时间
	*	@param	:	
	*	@retval	:	
	*/
bit SetDate(uint8 set_mode)
{
	uint32 temp;
	uint8 *str_addr, *p;
	const uint8 *str = ".", *str1 = ":";

	if(set_mode == 0)
		Uart2_SendStr("\r\n请设置年、月、日(格式:20xx.xx.xx+回车)(退出:x+回车)\r\n");
	else if(set_mode == 1)
		Uart2_SendStr("\r\n请设置时间(格式:xx:xx:+回车)\r\n");
	else if(set_mode == 2)
		Uart2_SendStr("\r\n请设置闹钟(格式:xx:xx:+回车)\r\n");
	while(1)
	{
		str_addr = Uart2_RecStr();
		if((strlen(str_addr)>0) && (strcmp(str_addr, "x")!=0))
		{
			Uart2_SendStr(str_addr);		// 蓝牙返回字符串,提示接收到
			if(set_mode == 0)
				p = strtok(str_addr, str);	// 切割字符串
			else if((set_mode==1) || (set_mode==2))
				p = strtok(str_addr, str1);	// 切割字符串
			temp = atoi(p);							// 数字字符串转整型数据
			if(set_mode == 0)
			{
				if((temp>=2000) && (temp<=2099))	// 判断年输入格式是否正确
				{
					RTC_Dat[0] = ((temp/10%10)<<4) | (temp%10);
					RTC_SetOne(RTC_Dat[0], RTC_Addr_W_Year);	// 设置年
					OLED_ShowString(0, 2, "Year:", 16);
					OLED_ShowString(40, 2, p, 16);
					
					p = strtok(NULL, str);
					temp = atoi(p);
					RTC_Dat[2] = ((temp/10%10)<<4) | (temp%10);
					RTC_SetOne(RTC_Dat[2], RTC_Addr_W_Month);	// 设置月
					OLED_ShowString(0, 4, "Month:", 16);
					OLED_ShowString(48, 4, p, 16);
					
					p = strtok(NULL, str);
					temp = atoi(p);
					RTC_Dat[3] = ((temp/10%10)<<4) | (temp%10);
					RTC_SetOne(RTC_Dat[3], RTC_Addr_W_Day);		// 设置日
					OLED_ShowString(0, 6, "Day:", 16);
					OLED_ShowString(32, 6, p, 16);
					
					memset(str_addr, 0, sizeof(str_addr));		// 清空字符串
					Uart2_SendStr("\r\n设置年月日成功\r\n");
					return 1;
				}
				else
				{
					temp = 0;
					memset(str_addr, 0, sizeof(str_addr));		// 清空字符串
					Uart2_SendStr("输入错误\r\n");
				}
			}
			else if((set_mode==1) || (set_mode==2))
			{
				if((temp>=0) && (temp<=23))	// 判断 时间 输入格式是否正确
				{
					if(set_mode==1)
					{
						RTC_Dat[4] = ((temp/10%10)<<4) | (temp%10);
						RTC_SetOne(RTC_Dat[4], RTC_Addr_W_Hour);	// 设置时
					}
					else if(set_mode==2)
					{
						Clocking[0] = ((temp/10%10)<<4) | (temp%10);	// 设置闹钟时
					}
					OLED_ShowString(64, 4, "Hour:", 16);
					OLED_ShowString(96, 4, p, 16);
					
					p = strtok(NULL, str1);
					temp = atoi(p);
					if(set_mode==1)
					{
						RTC_Dat[5] = ((temp/10%10)<<4) | (temp%10);
						RTC_SetOne(RTC_Dat[5], RTC_Addr_W_Min);		// 设置分
					}
					else if(set_mode==2)
					{
						Clocking[1] = ((temp/10%10)<<4) | (temp%10);	// 设置闹钟分
					}
					OLED_ShowString(64, 6, "Min:", 16);
					OLED_ShowString(96, 6, p, 16);
					
					memset(str_addr, 0, sizeof(str_addr));		// 清空字符串
					Uart2_SendStr("\r\n设置时分成功\r\n");
					delay_ms(500);
					return 1;
				}
				else
				{
					temp = 0;
					memset(str_addr, 0, sizeof(str_addr));		// 清空字符串
					Uart2_SendStr("输入错误\r\n");
				}
			}
		}
		else if(strcmp(str_addr, "x") == 0)
		{
			Uart2_SendStr("\r\n退出设置\r\n");
			memset(str_addr, 0, sizeof(str_addr));			// 清空字符串
			temp = 0;
			return 0;
		}
	}
}




/**
	*	@brief	:	闹钟检查函数
	*	@param	:	Min_Dat:分钟
	*	@retval	:	
	*/
void Clock_Check(uint8 Min_Dat)
{
	if(Min_Dat != Clocking[1])	// 若闹钟分钟未到
		return;
	
	if(Read_Ds1302_Byte(RTC_Addr_R_Hour) == Clocking[0])	// 若闹钟时分皆符合
	{
		ET1 = 0;		// 关T1中断
		OLED_Clear();
		OLED_DrawBMP(32, 0, 64, 64, BMP2);	// 显示闹钟提示
		while(1)
		{
			if(Uart2_RecByte() == '0')
			{
				Show_Info();										// 显示时钟界面
				Clocking[0] = Clocking[1] = 0;	// 清除闹钟
				CLOCK_FLAG = 0;
				break;
			}
			else
			{
				SPEAKER = ~SPEAKER;
				delay_ms(1);
			}
		}
		ET1 = 1;
	}
}

六、实物、功能展示

 

视频:多功能数字时钟(STC15)_哔哩哔哩_bilibili

七、源码+其它资料

链接:https://pan.baidu.com/s/1OkA2VG4j6fXIKFJ15vdRHA 
提取码:stej

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值