电子定时器小项目 (基于STM32f103ZET6)

    今天,想和大家分享的是一个电子计算器的小项目,这个项目也和蓝桥杯某一年的省赛题有点类似。

      这是我简单的绘制的一份流程图。可以存储5个定时的时间并且每一个都可以修改,通过while(1)循环一直判断是否有按键触发,WK_UP按下超过1.5秒开始定时并显示Runing,再次长按1.5秒则为暂停并显示Pause,暂停后也可以继续长按继续定时。KEY1按下可以选择1~5中的一个开始定时并显示Setting。KEY2按下后可分为四种状态,此时 WK_UP KEY1 KEY2 重新分别对应 时分秒 的设置,WK_UP和KEY2同时按下则为退出设置模式并显示为Standby。

    我用的是原子哥的精英板有三个按键,没有这么多的外接是一样的,废话不多说直接开始!!!

这里我开启了两个定时器,一个是记录长按的时间,另一个是开启定时后的定时功能。

这里我给大家看一下中断代码 tim代码大家自己配置一下。

void TIM3_IRQHandler(void)
{
	if( TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
	{
		Long_press++;
		if(++Flag%2==1)
		{
			LED0_O;//led0打开
			LED1_C;//led1关闭
		}
		else
		{
			LED0_C;//led0关闭
			LED1_O;//led1打开
			Flag=0;
			time_tim();//tim定时器开启 会一直调用该函数 直到倒计时结束
		}
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
	}
}

void TIM2_IRQHandler(void)
{
	if( TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
	{
		Long_press++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}

tim3的溢出时间为0.5秒,所以每进行一次else就是过了一秒的操作,并且计时的过程中有一个两灯交替的效果。


u16 hms[5][3]={            //存储5个时间点  hh:mm:ss
								{0,1,5},
								{0,6,0},
								{0,0,60},
								{0,0,30},
								{0,0,10}
							};			

///
//      Long_press  :  长按开始计时的falg                       //  
//      WK_UP_flag  :  长按判断开还是关的falag                  // 
//      count       :  记录按下的次数 NO.X                      // 
//      Set_time    :  记录NO.X 做设置时间用 如gms[Set_time][x] // 
//      set_Moed_flag :记录模式的flag                           // 							
///		   
							
u8 Long_press=0,WK_UP_flag=1;
u8 h,m,s;
u8 count=0,Set_time=0,set_Moed_flag=0;
int main(void)
{
	h=hms[0][0],m=hms[0][1],s=hms[0][2];//时间初始化为数据的第一行元素
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//中断分组
	Init();//初始化
	OLED_Clear(0);//清除屏幕
	time(count);//1
	Mode(Standby);//2   (1,2)为初始化上电屏幕显示
	while(1)
	{
		if(WK_UP)//判断WK_UP按键是否按下
		{
			delay_ms(100);//延时防抖
			if(Long_press==2&&WK_UP_flag==1)
			{
				open_Timing();//打开定时器计数
			}
		 if(Long_press==2&&WK_UP_flag==0)
			{
				close_Timing();//关闭定时器计数
			}
		}
		else//如没有按下WK_UP,Long_press一直为0,按下过后超过两秒进行开关定时器计数
		{
			Long_press=0;
		}
		
			
//如果KEY1按下 并且没有计数的情况下 则为选择计数NO.X
		if(KEY1&&WK_UP_flag==1)
		{
			
			delay_ms(300);//防抖
			time(count);//每按下一次就会改变屏幕的显示
			Mode(Setting);//2 并且把模式显示为Setting
			if(++count==5)
				 count=0;
		}
		
		
//KEY2按下并且模式为Setting情况下 可设置时分秒数值
		if(KEY2&&set_Moed_flag==1)
		{
			while(1)
			{
				delay_ms(50);
				if(WK_UP&&KEY2)//WK_UP和KEY2同时按下为退出更改模式
				{
					delay_ms(500);//防抖
					Mode(Standby);//设置模式为Standby
					break;//退出大循环
				}
				else if(KEY2)//此时如果按下的是KEY2 则改变秒钟
				{
					delay_ms(50);
					s++;
					if(s>59)//大于59重置
						s=0;
					hms[Set_time][2]=s;//改变hms数组里面的内容
					OLED_ShowNum(90,3,s,2,16);//改变显示
				}
				else if(KEY1)//改变分钟 同上
				{
					delay_ms(50);
					m++;
					if(m>59)
						m=0;
					hms[Set_time][1]=m;
					OLED_ShowNum(50,3,m,2,16);
				}
				else if(WK_UP)//改变小时 同上
				{
					delay_ms(50);
					h++;
					if(h>59)
						h=0;
					hms[Set_time][0]=h;
					OLED_ShowNum(10,3,h,2,16);
				}
				
			}
		}
	}
}

这是主函数,定义了一个5*3二维数组用来存放时间。while(1)里面每一句都有详细的解释。大家仔细看一下。简单来说就是一直检测三个按键是否触发。


void time(u8 count)//改变NO.X 已经记录Set_time 和重新赋值 h m s
{
	switch(count)
	{
		case 0: OLED_ShowString(10,0,"NO.1",16);Set_time=0;h=hms[0][0],m=hms[0][1],s=hms[0][2];break;
		case 1: OLED_ShowString(10,0,"NO.2",16);Set_time=1;h=hms[1][0],m=hms[1][1],s=hms[1][2];break;
    case 2: OLED_ShowString(10,0,"NO.3",16);Set_time=2;h=hms[2][0],m=hms[2][1],s=hms[2][2];break;
    case 3: OLED_ShowString(10,0,"NO.4",16);Set_time=3;h=hms[3][0],m=hms[3][1],s=hms[3][2];break;
    case 4:	OLED_ShowString(10,0,"NO.5",16);Set_time=4;h=hms[4][0],m=hms[4][1],s=hms[4][2];break;
		default:break;
	}
	Calobrate_time();//显示时间校准
}

void close_Timing(void)//关闭定时器功能
{
				delay_ms(500);
				TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE);
				WK_UP_flag=1;
				Mode(Pause);//显示暂停
}


void open_Timing(void)//打开定时器功能
{
				TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
				WK_UP_flag=0;
				Mode(Runing);//显示正在运行
}


void time_tim()//tim定时器开启 会一直调用该函数 直到倒计时结束
{
	if(h!=0||m!=0||s!=0)
	{
		if(s--==0)
		{
			if(m!=0)
				{
					m--;s=59;
				}
			  else
			  {
				  if(h!=0)
					{
						h--;m=59;s=59;
					}
			  }		
		}
		Calobrate_time();
	}
	else
	{
		close_Timing();
	}
}

void Mode(u8 i)//模式的选择
{
	switch(i)
	{
		case 0: OLED_ShowString(40,6,"Standby",16);set_Moed_flag=0; break;
		case 1: OLED_ShowString(40,6,"Setting",16);set_Moed_flag=1;break;
    case 2: OLED_ShowString(40,6,"Runing",16);set_Moed_flag=2;break;
		case 3: OLED_ShowString(40,6,"Pause",16);set_Moed_flag=3;break;
		default:break;
	}
}

void Calobrate_time(void)//校准时间
{
	OLED_ShowNum(10,3,h,2,16);
	OLED_ShowString(35,3,":",16);
	OLED_ShowNum(50,3,m,2,16);
	OLED_ShowString(75,3,":",16);
	OLED_ShowNum(90,3,s,2,16);
}

这是一些对应的函数处理。h m s为全局变量,当开始定时时就会每过一秒就会调用一次time_tim()

进行减操作,每减成功后也会调用一次calobrate_time进行屏幕上的校准。

#ifndef _MAIN_H
#define _MAIN_H
#include "stm32f10x.h"
#define Standby 0
#define Setting 1
#define Runing 2
#define Pause 3
void time(u8 count);
void Mode(u8 i);
void time_tim(void);
void Delay(u16 conut);
void open_Timing(void);
void close_Timing(void);
void Calobrate_time(void);
#endif

这是main.h文件对照着上面一起看。代码有点多,感兴趣的盆友可以看看。

能力有限,不喜勿喷。下面是对应的视频展示和源代码,有兴趣可以看一下。

视频链接:https://b23.tv/znRKef7

链接:https://pan.baidu.com/s/1e7WSkfnJRi_Us-pYgpOvUw?pwd=qlmy 
提取码:qlmy

  • 9
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只想做好编程的小王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值