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

这是我简单的绘制的一份流程图。可以存储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://pan.baidu.com/s/1e7WSkfnJRi_Us-pYgpOvUw?pwd=qlmy
提取码:qlmy
文章目录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.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,
我想验证一个电子邮件地址是否是PayPal用户。是否有API调用来执行此操作?是否有执行此操作的ruby库?谢谢 最佳答案 GetVerifiedStatus来自PayPal'sAdaptiveAccounts平台会为您做这件事。PayPal没有任何codesamples或SDKs用于Ruby中的自适应帐户,但我确实找到了编写codeforGetVerifiedStatusinRuby的人.您需要更改该代码以检查他们拥有的帐户类型的唯一更改是更改if@xml['accountStatus']!=nilaccount_status
我想知道我应该如何着手这个项目。我需要每周向人们发送一次电子邮件。但是,这必须在每周的特定时间自动生成并发送。编码有多难?我需要知道是否有任何书籍可以提供帮助,或者你们中的任何人是否可以指导我。它必须使用rubyonrails进行编程。因此有一个网络服务和数据库集成。干杯 最佳答案 为什么这么复杂?您只需安排工作。您可以使用Delayed::Job例如。Delayed::Job让您可以使用run_at符号在特定时间安排作业,如下所示:Delayed::Job.enqueue(SendEmailJob.new(...),:run_
LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L
我正在尝试使用IMAP和rubymailgem获取gmail的正文。当我按照anotherstackoverflowanswer.中的描述获取RFC822字段时,它工作得很好.Fiedl很好地描述了这种方法answer类似的问题。这种方法很棒,只是它需要获取RFC822,而RFC822也会获取所有附件。是否有任何其他领域或其他方法我可以采取不获取附件但仍然使用rubymailgem来获得解码良好的正文? 最佳答案 您必须解析并理解返回的BODYSTRUCTURE响应的实际结构,请参阅RFC3501,p.56.还要记住应用相关
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解决方案。 最佳答案 我最终
我正在从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
我正在使用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
目录一、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)双模解决方
有道无术,术尚可求,有术无道,止于术。本系列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