【STM32单片机】多功能时钟菜单设计


一、功能简介

本项目使用STM32F103C8T6单片机控制器,使用按键、IIC OLED模块、DS18B20温度传感器、蜂鸣器等。
主要功能:
系统运行后,OLED液晶显示默认以数字样式显示时钟和温度;可按下K4键进入功能选项界面,K1和K2键用于选择,系统预置了4个功能,
分别是设置、计算器、游戏、秒表,其中计算器未设置功能,为用户预留;选择好功能选项后,按K4进入,设置选项功能里面有3个子功能,
分别是时间设置、闹钟设置、温度阈值,可通过K1和K2键选择子功能,K4键进入,如需返回上一级界面可按下K3键;
进入时间设置子功能,默认处于秒选中,可通过K3键切换相应位置,K1和K2用于时间调节,并且时间样式也可以选择为表盘和数字,
选择完成可按下K4键确定并返回上一级界面,如不需保存可直接按下K1+K3键返回;
进入闹钟设置子功能,默认处于分选中,可通过K3键切换相应位置,K1和K2用于时间调节,并且闹钟可设置开关,
选择完成可按下K4键确定并返回上一级界面;
进入温度阈值子功能,默认处于温度下限选中,可通过K3键切换相应位置,K1和K2用于温度调节,选择完成可按下K4键确定并返回上一级界面;
在功能选择界面,进入推箱子游戏功能,默认从第一关开始,K1、K2、K3、K4分别对应方向上、下、左、右;如需返回上一级界面可按下K1+K3键;
在功能选择界面,进入秒表功能,可按下K1键启动秒表计时,再次按下K1键记录第1次时间,再次按下K1键记录第2次,最多可记录3次;按下K2键停止,
然后需要启动可按下K1键重新开始记录;按下K4键清除计时;需要返回可按下K3键;


二、软件设计

/*
作者:嗨小易(QQ:3443792007)

*/


//秒表模式显示
void _stopwatch_mode_show(void)
{
	u8 key=0;
	u8 min[3]={0};
	u8 sec[3]={0};
	u8 msec[3]={0};
	u8 cnt=0;
	u8 oneflag=0;
	
	sys_ctrl.min=0;sys_ctrl.sec=0;sys_ctrl.msec=0;
	TIM3_Init(20,36000-1);  //定时10ms
	OLED_Clear();//清屏
	OLED_ShowString(35,0,"00:00:",16);
	OLED_ShowString(35+6*8,4,"00",12);
	
	while(1)
	{
		key=KEY_Scan(0);
		//开始,记录
		if(key==KEY1_PRESS)
		{
			if(oneflag==0)
			{
				oneflag=1;TIM_Cmd(TIM3,ENABLE); //打开定时器
			}
			else
			{
				min[cnt]=sys_ctrl.min;
				sec[cnt]=sys_ctrl.sec;
				msec[cnt]=sys_ctrl.msec;
				//记录秒表时间显示
				OLED_ShowxNum(20,20+cnt*14,min[cnt],2,12,0x80,1);
				OLED_ShowString(20+2*6,20+cnt*14,":",12);
				OLED_ShowxNum(20+3*6,20+cnt*14,sec[cnt],2,12,0x80,1);
				OLED_ShowString(20+5*6,20+cnt*14,":",12);
				OLED_ShowxNum(20+6*6,20+cnt*14,msec[cnt],2,12,0x80,1);
				cnt++;
				if(cnt>2)cnt=0;
			}				
		}
		//停止
		else if(key==KEY2_PRESS)
		{
			oneflag=0;
			TIM_Cmd(TIM3,DISABLE); //关闭定时器
			sys_ctrl.min=0;sys_ctrl.sec=0;sys_ctrl.msec=0;
		}
		//返回
		else if(key==KEY3_PRESS)
		{
			sys_ctrl.setmode=0;
			sys_ctrl.min=0;sys_ctrl.sec=0;sys_ctrl.msec=0;
			break;
		}
		//清除
		else if(key==KEY4_PRESS)
		{
			sys_ctrl.min=0;sys_ctrl.sec=0;sys_ctrl.msec=0;
			cnt=0;
			OLED_Fill(20,20,20+8*6,60,0);
		}
		//秒表显示
		OLED_ShowxNum(35,0,sys_ctrl.min,2,16,0x80,1);
		OLED_ShowxNum(35+3*8,0,sys_ctrl.sec,2,16,0x80,1);
		OLED_ShowxNum(35+6*8,4,sys_ctrl.msec,2,12,0x80,1);
		
		OLED_Refresh_Gram();//刷新显存
	}
}

//游戏过关判定
//返回1过关,0未过关
u8 game_pass(void)
{
	u8 i=0,k=0;

	for(i=0;i<MAP_ROW;i++)
	{
		for(k=0;k<MAP_COL;k++)
		{
			if(map[glevel][i][k]==BOX)
				return 0;
		}
	}
	return 1;
}
//游戏模式显示
void _game_mode_show(void)
{
	OLED_Clear();//清屏

	while(1)
	{
		//游戏过关
		if(game_pass())
		{
			glevel++;
			if(glevel>GAME_CENSOR)
			{
				//游戏通过
				OLED_Clear();
				OLED_ShowString(10,10,"Game Pass",16);
				OLED_ShowString(10,30,"Reset Start",16);
				OLED_Refresh_Gram();
				while(1);
			}
		}
		OLED_ShowFontHZ(X_WIDTH-40,10,21,16,1);//第
		OLED_ShowNum(X_WIDTH-24,10,glevel+1,1,16);
		OLED_ShowFontHZ(X_WIDTH-16,10,22,16,1);//关
		
		game_draw();//游戏界面绘制
		key_event();//按键消息处理
		
		//两个键按下时则退出
		if(KEY3==0 && KEY1==0)
		{
			delay_ms(10);
			if(KEY3==0 && KEY1==0)
				break;
		}
	}
}

//模式控制
void mode_ctrl(void)
{
	if(sys_ctrl.set==1)//进入设置
	{
		switch(sys_ctrl.mode)
		{
			case 1:_set_mode_show();break;
			case 2:break;
			case 3:_game_mode_show();break;
			case 4:_stopwatch_mode_show();break;
		}
	}
}

//应用控制系统
void app_sys_ctrl_demo(void)
{
	u8 i=10;
	
	LED_Init();
	USART1_Init(115200);
	OLED_Init();
	KEY_Init();
	BEEP_Init();
	DS18B20_Init();
	RTC_Init();
	//获取稳定数据
	while(i--)
	{
		sys_ctrl.temp=DS18B20_GetTemperture()*10;
		delay_ms(100);
	}
	OLED_Init();
	TIM4_Init(100,36000-1);  //定时50ms
	sys_parm_init();//系统参数初始化
	while(1)
	{
		rtc_temp_show();//时钟温度显示
		mode_switch_show();//模式选择显示
		mode_ctrl();//模式控制
	}
}

/*******************************************************************************
* 函 数 名         : TIM4_IRQHandler
* 函数功能		   : TIM4中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void TIM4_IRQHandler(void)
{
	static u8 cnt=0;
	static u8 i=0;
	if(TIM_GetITStatus(TIM4,TIM_IT_Update))
	{
		if(calendar.hour==sys_ctrl.alarm_time[0])
		{
			if(calendar.min==sys_ctrl.alarm_time[1])
			{
				sys_ctrl.alarm_flag=1;//闹钟到达
			}
		}
		if(sys_ctrl.alarm_flag)
		{
			i++;
			if(i%10==0)
			{
				BEEP_Alarm(50,100);
				cnt++;
				if(cnt>5)
				{
					cnt=0;sys_ctrl.alarm_flag=0;
				}
			}
		}
	}
	TIM_ClearITPendingBit(TIM4,TIM_IT_Update);	
}

/*******************************************************************************
* 函 数 名         : TIM3_IRQHandler
* 函数功能		   : TIM3中断函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update))
	{
		sys_ctrl.msec++;
		if(sys_ctrl.msec>=100)
		{
			sys_ctrl.msec=0;
			sys_ctrl.sec++;
			if(sys_ctrl.sec>59)
			{
				sys_ctrl.sec=0;
				sys_ctrl.min++;
				if(sys_ctrl.min>59)sys_ctrl.min=0;
			}
		}
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);	
}



三、实验现象

B站演示视频:https://space.bilibili.com/444388619

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


联系作者

专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值