今天,想和大家分享的是一个电子计算器的小项目,这个项目也和蓝桥杯某一年的省赛题有点类似。
这是我简单的绘制的一份流程图。可以存储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