草庐IT

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

只想做好编程的小王 2023-04-08 原文

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

      这是我简单的绘制的一份流程图。可以存储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

有关电子定时器小项目 (基于STM32f103ZET6)的更多相关文章

  1. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  2. ruby-on-rails - 验证电子邮件地址是 Paypal 用户 - 2

    我想验证一个电子邮件地址是否是PayPal用户。是否有API调用来执行此操作?是否有执行此操作的ruby​​库?谢谢 最佳答案 GetVerifiedStatus来自PayPal'sAdaptiveAccounts平台会为您做这件事。PayPal没有任何codesamples或SDKs用于Ruby中的自适应帐户,但我确实找到了编写codeforGetVerifiedStatusinRuby的人.您需要更改该代码以检查他们拥有的帐户类型的唯一更改是更改if@xml['accountStatus']!=nilaccount_status

  3. ruby-on-rails - Ruby on Rails - 需要在每周的特定时间将消息发送到电子邮件 - 2

    我想知道我应该如何着手这个项目。我需要每周向人们发送一次电子邮件。但是,这必须在每周的特定时间自动生成并发送。编码有多难?我需要知道是否有任何书籍可以提供帮助,或者你们中的任何人是否可以指导我。它必须使用ruby​​onrails进行编程。因此有一个网络服务和数据库集成。干杯 最佳答案 为什么这么复杂?您只需安排工作。您可以使用Delayed::Job例如。Delayed::Job让您可以使用run_at符号在特定时间安排作业,如下所示:Delayed::Job.enqueue(SendEmailJob.new(...),:run_

  4. STM32的HAL和LL库区别和性能对比 - 2

    LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L

  5. ruby - 使用ruby mail gem获取电子邮件正文而不获取附件 - 2

    我正在尝试使用IMAP和ruby​​mailgem获取gmail的正文。当我按照anotherstackoverflowanswer.中的描述获取RFC822字段时,它工作得很好.Fiedl很好地描述了这种方法answer类似的问题。这种方法很棒,只是它需要获取RFC822,而RFC822也会获取所有附件。是否有任何其他领域或其他方法我可以采取不获取附件但仍然使用ruby​​mailgem来获得解码良好的正文? 最佳答案 您必须解析并理解返回的BODYSTRUCTURE响应的实际结构,请参阅RFC3501,p.56.还要记住应用相关

  6. ruby - 使用 S/MIME 在 Ruby 中对电子邮件进行数字签名 - 2

    Ruby中是否有一种方法可以使用S/MIME对电子邮件消息进行数字签名?我们的团队使用PKI,我们的用户习惯于期待重要消息的数字签名。我知道我可以调用openssl命令行工具:opensslsmime-sign-signer$CERT_FILE-passinpass:$CERT_PASS-in$UNSIGNED_MAIL-out$SIGNED_MAIL-certfile$CERT_CA_FILE-from'your'-to'recipients'-subject'TheSubject'但我希望利用Ruby解决方案。 最佳答案 我最终

  7. ruby-on-rails - 发生异常时发送电子邮件不起作用,使用 exception_notification - 2

    我正在从rails2.3迁移到rails3.1,我试图在生成异常时发送电子邮件。我正在使用exception_notificationgem。我的其余电子邮件都在工作。但是异常邮件不会被解雇。以下是我的staging.rb文件中的设置。config.action_mailer.perform_deliveries=trueconfig.action_mailer.raise_delivery_errors=true下面是application.rb中的代码C::Application.config.middleware.useExceptionNotification::Rack,:e

  8. ruby - 使用 gmail gem 跟踪一些电子邮件 - 2

    我正在使用gmailgem发送电子邮件,我需要跟踪这些电子邮件。我该怎么做?我正在尝试搜索带有message_id的电子邮件,但它会从我的收件箱中提取所有电子邮件,而我只想要特定电子邮件的回复。这是我的实际代码:*使用message_id保存电子邮件*mail=gmail.deliver(email)Email.create(:message_id=>mail.message_id,:from=>user.email,:to=>annotation.to,:body=>annotation.content,:title=>annotation.title,:annotation=>an

  9. ESP32学习入门:WiFi连接网络 - 2

    目录一、ESP32简单介绍二、ESP32Wi-Fi模块介绍三、ESP32Wi-Fi编程模型四、ESP32Wi-Fi事件处理流程 五、ESP32Wi-Fi开发环境六、ESP32Wi-Fi具体代码七、ESP32Wi-Fi代码解读6.1主程序app_main7.2自定义代码wifi_init_sta()八、ESP32Wi-Fi连接验证8.1测试方法8.2服务器模拟工具sscom58.3测试代码8.4测试结果前言为了开发一款亚马逊物联网产品,开始入手ESP32模块。为了能够记录自己的学习过程,特记录如下操作过程。一、ESP32简单介绍ESP32是一套Wi-Fi(2.4GHz)和蓝牙(4.2)双模解决方

  10. Spring Security 6.0系列【32】授权服务器篇之默认过滤器 - 2

    有道无术,术尚可求,有术无道,止于术。本系列SpringBoot版本3.0.4本系列SpringSecurity版本6.0.2本系列SpringAuthorizationServer版本1.0.2源码地址:https://gitee.com/pearl-organization/study-spring-security-demo文章目录前言1.OAuth2AuthorizationServerMetadataEndpointFilter2.OAuth2AuthorizationEndpointFilter3.OidcProviderConfigurationEndpointFilter4.N

随机推荐