【STM32单片机】智能时钟设计


一、功能简介

本项目使用STM32F103C8T6单片机控制器,使用无源蜂鸣器模块、IIC OLED显示模块、DS18B20温度传感器、独立按键等。

主要功能:
系统运行后,OLED显示温度、日期和时间;
可按下K3键进入时间修改模式,K4键用于选择修改位置,K1和K2键调节;再次按下K3键进入闹钟设置模式,K4键用于选择修改位置,K1和K2调节;当打开闹钟开关后,到达设定闹钟时间,开始闹铃,30S后自动关闭,也可通过K3键手动关闭闹铃。


二、软件设计

/*
作者:嗨小易(技术交流QQ群:570487280)

*/



//系统数据显示
void sys_data_show(void)
{
   
	u8 buf[9];
	while(1)
	{
   
		//正常模式显示
		if(sys_ctrl.mode==0)
		{
   
			//温度显示
			buf[0]=sys_ctrl.temp/100+0x30;
			buf[1]=sys_ctrl.temp%100/10+0x30;
			buf[2]='.';
			buf[3]=sys_ctrl.temp%100%10+0x30;
			buf[4]='\0';
			OLED_ShowString(5*8,0,buf,16);
			//日期显示
			buf[0]=sys_ctrl.time[0]%100/10+0x30;
			buf[1]=sys_ctrl.time[0]%100%10+0x30;
			buf[2]='-';
			buf[3]=sys_ctrl.time[1]/10+0x30;
			buf[4]=sys_ctrl.time[1]%10+0x30;
			buf[5]='-';
			buf[6]=sys_ctrl.time[2]/10+0x30;
			buf[7]=sys_ctrl.time[2]%10+0x30;
			buf[8]='\0';
			OLED_ShowString(8*8,20,buf,16);
			//时间显示
			buf[0]=sys_ctrl.time[3]%100/10+0x30;
			buf[1]=sys_ctrl.time[3]%100%10+0x30;
			buf[2]=':';
			buf[3]=sys_ctrl.time[4]/10+0x30;
			buf[4]=sys_ctrl.time[4]%10+0x30;
			buf[5]=':';
			buf[6]=sys_ctrl.time[5]/10+0x30;
			buf[7]=sys_ctrl.time[5]%10+0x30;
			buf[8]='\0';
			OLED_ShowString(8*8,40,buf,16);
			//星期1-7显示
			buf[0]=sys_ctrl.time[6]+0x30;
			buf[1]='\0';
			OLED_ShowString(15*8,0,buf,16);
		}
		//调整时间显示
		else if(sys_ctrl.mode==1) 
		{
   
			//日期时间选择
			switch(sys_ctrl.cnt)
			{
   
				case 0://年
					buf[0]=sys_ctrl.time[6]%10+0x30;
					buf[1]='\0';
					OLED_ShowStringex(15*8,0,buf,16,1);
					buf[0]=sys_ctrl.time[0]%100/10+0x30;
					buf[1]=sys_ctrl.time[0]%100%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(8*8,20,buf,16,0);
					break;
				case 1://月
					buf[0]=sys_ctrl.time[0]%100/10+0x30;
					buf[1]=sys_ctrl.time[0]%100%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(8*8,20,buf,16,1);
					buf[0]=sys_ctrl.time[1]/10+0x30;
					buf[1]=sys_ctrl.time[1]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(11*8,20,buf,16,0);
					break;
				case 2://日
					buf[0]=sys_ctrl.time[1]/10+0x30;
					buf[1]=sys_ctrl.time[1]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(11*8,20,buf,16,1);
					buf[0]=sys_ctrl.time[2]/10+0x30;
					buf[1]=sys_ctrl.time[2]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(14*8,20,buf,16,0);
					break;
				case 3://时
					buf[0]=sys_ctrl.time[2]/10+0x30;
					buf[1]=sys_ctrl.time[2]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(14*8,20,buf,16,1);
					buf[0]=sys_ctrl.time[3]/10+0x30;
					buf[1]=sys_ctrl.time[3]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(8*8,40,buf,16,0);
					break;
				case 4://分
					buf[0]=sys_ctrl.time[3]/10+0x30;
					buf[1]=sys_ctrl.time[3]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(8*8,40,buf,16,1);
					buf[0]=sys_ctrl.time[4]/10+0x30;
					buf[1]=sys_ctrl.time[4]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(11*8,40,buf,16,0);
					break;
				case 5://秒
					buf[0]=sys_ctrl.time[4]/10+0x30;
					buf[1]=sys_ctrl.time[4]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(11*8,40,buf,16,1);
					buf[0]=sys_ctrl.time[5]/10+0x30;
					buf[1]=sys_ctrl.time[5]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(14*8,40,buf,16,0);
					break;
				case 6://星期
					buf[0]=sys_ctrl.time[5]/10+0x30;
					buf[1]=sys_ctrl.time[5]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(14*8,40,buf,16,1);
					buf[0]=sys_ctrl.time[6]%10+0x30;
					buf[1]='\0';
					OLED_ShowStringex(15*8,0,buf,16,0);
					break;
			}
		}
		//闹钟设置显示
		else if(sys_ctrl.mode==2)
		{
   
			buf[0]=sys_ctrl.alarm_time[0]/10+0x30;
			buf[1]=sys_ctrl.alarm_time[0]%10+0x30;
			buf[2]='\0';
			OLED_ShowStringex(6*8,30,buf,16,1);
			buf[0]=sys_ctrl.alarm_time[1]/10+0x30;
			buf[1]=sys_ctrl.alarm_time[1]%10+0x30;
			buf[2]='\0';
			OLED_ShowStringex(9*8,30,buf,16,1);
			
			//时间选择
			switch(sys_ctrl.cnt)
			{
   
				case 0://闹钟开关
					buf[0]=sys_ctrl.alarm_time[1]/10+0x30;
					buf[1]=sys_ctrl.alarm_time[1]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(9*8,30,buf,16,1);
					if(sys_ctrl.alarm_onoff==1)OLED_ShowStringex(6*8,0," ON",16,0);
					else OLED_ShowStringex(6*8,0,"OFF",16,0);
					break;
				case 1://时
					if(sys_ctrl.alarm_onoff==1)OLED_ShowStringex(6*8,0," ON",16,1);
					else OLED_ShowStringex(6*8,0,"OFF",16,1);
					buf[0]=sys_ctrl.alarm_time[0]/10+0x30;
					buf[1]=sys_ctrl.alarm_time[0]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(6*8,30,buf,16,0);
					break;
				case 2://分
					buf[0]=sys_ctrl.alarm_time[0]/10+0x30;
					buf[1]=sys_ctrl.alarm_time[0]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(6*8,30,buf,16,1);
					buf[0]=sys_ctrl.alarm_time[1]/10+0x30;
					buf[1]=sys_ctrl.alarm_time[1]%10+0x30;
					buf[2]='\0';
					OLED_ShowStringex(9*8,30,buf,16,0);
					break;
			}
		}
		
		OLED_Refresh_Gram();//刷新显示缓存
		break;
	}
}

//系统数据设置
void sys_data_set(void)
{
   
	u8 key=0;
	
	key=KEY_Scan(0);
	
	//设置
	if(key==KEY3_PRESS)
	{
   
		if(sys_ctrl.alarm_flag==0)//闹钟还未启动
		{
   
			sys_ctrl.cnt=0;
			sys_ctrl.mode++;
			if(sys_ctrl.mode>2)
			{
   
				sys_ctrl.mode=0;
				RTC_Set(sys_ctrl.time[0],sys_ctrl.time[1],sys_ctrl.time[2],sys_ctrl.time[3],sys_ctrl.time[4],sys_ctrl.time[5]);
				sys_open_show();//系统开机界面显示
			}
			if(sys_ctrl.mode==2)
			{
   
				//记录当前时间,作为报警时间起点
				sys_ctrl.alarm_time[0]=sys_ctrl.time[3];
				sys_ctrl.alarm_time[1]=sys_ctrl.time[4];
				alarm_set_show();//闹钟设置界面显示
			}
		}
		else//闹钟已启动,可手动K3键关闭
		{
   
			sys_ctrl.alarm_flag=0;
		}
	}
	//时间修改设置
	if(sys_ctrl.mode==1)
	{
   
		//选择
		if(key==KEY4_PRESS)
		{
   
			sys_ctrl.cnt++;
			if(sys_ctrl.cnt>6)sys_ctrl.cnt=0;
		}
		//加
		else if(key==KEY1_PRESS)
		{
   
			switch(sys_ctrl.cnt)
			{
   
				case 0://年
					sys_ctrl.time[0]++;
					if(sys_ctrl.time[0]>2099)sys_ctrl.time[0]=0;
					break;
				case 1://月
					sys_ctrl.time[1]++;
					if(sys_ctrl.time[1]>12)sys_ctrl.time[1]=1;
					break;
				case 2://日
					sys_ctrl.time[2]++;
					if(sys_ctrl.time[2]>31)sys_ctrl.time[2]=1;
					break;
				case 3://时
					sys_ctrl.time[3]++;
					if(sys_ctrl.time[3]>23)sys_ctrl.time[3]=0;
					break;
				case 4://分
					sys_ctrl.time[4]++;
					if(sys_ctrl.time[4]>59)sys_ctrl.time[4]=0;
					break;
				case 5://秒
					sys_ctrl.time[5]++;
					if(sys_ctrl.time[5]>59)sys_ctrl.time[5]=0;
					break;
				case 6://星期
					sys_ctrl.time[6]++;
					if(sys_ctrl.time[6]>6)sys_ctrl.time[6]=0;
					break;
			}
		}
		//减
		else if(key==KEY2_PRESS)
		{
   
			switch(sys_ctrl.cnt)
			{
   
				case 0://年
					sys_ctrl.time[0]--;
					if(sys_ctrl.time[0]<0)sys_ctrl.time[0]=2099;
					break;
				case 1://月
					sys_ctrl.time[1]--;
					if(sys_ctrl.time[1]<1)sys_ctrl.time[1]=12;
					break;
				case 2://日
					sys_ctrl.time[2]--;
					if(sys_ctrl.time[2]<1)sys_ctrl.time[2]=31;
					break;
				case 3://时
					sys_ctrl.time[3]--;
					if(sys_ctrl.time[3]<0)sys_ctrl.time[3]=23;
					break;
				case 4://分
					sys_ctrl.time[4]--;
					if(sys_ctrl.time[4]<0)sys_ctrl.time[4]=59;
					break;
				case 5://秒
					sys_ctrl.time[5]--;
					if(sys_ctrl.time[5]<0)sys_ctrl.time[5]=59;
					break;
				case 6://星期
					sys_ctrl.time[6]--;
					if(sys_ctrl.time[6]<0)sys_ctrl.time[6]=6;
					break;
			}
		}
	}
	//闹钟设置
	if(sys_ctrl.mode==2)
	{
   
		//选择
		if(key==KEY4_PRESS)
		{
   
			sys_ctrl.cnt++;
			if(sys_ctrl.cnt>2)sys_ctrl.cnt=0;
		}
		//加
		else if(key==KEY1_PRESS)
		{
   
			switch(sys_ctrl.cnt)
			{
   
				case 0://开关
					sys_ctrl.alarm_onoff=!sys_ctrl.alarm_onoff;
					break;
				case 1://时
					sys_ctrl.alarm_time[0]++;
					if(sys_ctrl.alarm_time[0]>23)sys_ctrl.alarm_time[0]=0;
					break;
				case 2://分
					sys_ctrl.alarm_time[1]++;
					if(sys_ctrl.alarm_time[1]>59)sys_ctrl.alarm_time[1]=0;
					break;
			}
		}
		//减
		else if(key==KEY2_PRESS)
		{
   
			switch(sys_ctrl.cnt)
			{
   
				case 0://开关
					sys_ctrl.alarm_onoff=!sys_ctrl.alarm_onoff;
					break;
				case 1://时
					sys_ctrl.alarm_time[0]--;
					if(sys_ctrl.alarm_time[0]<0)sys_ctrl.alarm_time[0]=23;
					break;
				case 2://分
					sys_ctrl.alarm_time[1]--;
					if(sys_ctrl.alarm_time[1]<0)sys_ctrl.alarm_time[1]=59;
					break;
			}
		}
	}
}



三、实验现象

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

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


联系作者

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

最近更新

  1. TCP协议是安全的吗?

    2024-01-12 21:12:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-12 21:12:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-12 21:12:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-12 21:12:01       18 阅读

热门阅读

  1. 区块链知识学习(一)

    2024-01-12 21:12:01       31 阅读
  2. docker run命令

    2024-01-12 21:12:01       34 阅读
  3. WebSocket--整合springboot

    2024-01-12 21:12:01       28 阅读
  4. 2085. 统计出现过一次的公共字符串

    2024-01-12 21:12:01       40 阅读
  5. 2401C++,C++自动注册

    2024-01-12 21:12:01       37 阅读
  6. 【Android 10 适配】隐私权限变更

    2024-01-12 21:12:01       30 阅读