一、功能简介
本项目使用STM32F103C8T6单片机控制器,使用按键、IIC OLED模块、DS18B20温度传感器、蜂鸣器等。
主要功能:
系统运行后,OLED液晶显示默认以数字样式显示时钟和温度;可按下K4键进入功能选项界面,K1和K2键用于选择,系统预置了4个功能,
分别是设置、计算器、游戏、秒表,其中计算器未设置功能,为用户预留;选择好功能选项后,按K4进入,设置选项功能里面有3个子功能,
分别是时间设置、闹钟设置、温度阈值,可通过K1和K2键选择子功能,K4键进入,如需返回上一级界面可按下K3键;
进入时间设置子功能,默认处于秒选中,可通过K3键切换相应位置,K1和K2用于时间调节,并且时间样式也可以选择为表盘和数字,
选择完成可按下K4键确定并返回上一级界面,如不需保存可直接按下K1+K3键返回;
进入闹钟设置子功能,默认处于分选中,可通过K3键切换相应位置,K1和K2用于时间调节,并且闹钟可设置开关,
选择完成可按下K4键确定并返回上一级界面;
进入温度阈值子功能,默认处于温度下限选中,可通过K3键切换相应位置,K1和K2用于温度调节,选择完成可按下K4键确定并返回上一级界面;
在功能选择界面,进入推箱子游戏功能,默认从第一关开始,K1、K2、K3、K4分别对应方向上、下、左、右;如需返回上一级界面可按下K1+K3键;
在功能选择界面,进入秒表功能,可按下K1键启动秒表计时,再次按下K1键记录第1次时间,再次按下K1键记录第2次,最多可记录3次;按下K2键停止,
然后需要启动可按下K1键重新开始记录;按下K4键清除计时;需要返回可按下K3键;
二、软件设计
/*
作者:嗨小易(QQ:3443792007)
*/
//秒表模式显示
void _stopwatch_mode_show(void)
{
u8 key=0;
u8 min[3]={0};
u8 sec[3]={0};
u8 msec[3]={0};
u8 cnt=0;
u8 oneflag=0;
sys_ctrl.min=0;sys_ctrl.sec=0;sys_ctrl.msec=0;
TIM3_Init(20,36000-1); //定时10ms
OLED_Clear();//清屏
OLED_ShowString(35,0,"00:00:",16);
OLED_ShowString(35+6*8,4,"00",12);
while(1)
{
key=KEY_Scan(0);
//开始,记录
if(key==KEY1_PRESS)
{
if(oneflag==0)
{
oneflag=1;TIM_Cmd(TIM3,ENABLE); //打开定时器
}
else
{
min[cnt]=sys_ctrl.min;
sec[cnt]=sys_ctrl.sec;
msec[cnt]=sys_ctrl.msec;
//记录秒表时间显示
OLED_ShowxNum(20,20+cnt*14,min[cnt],2,12,0x80,1);
OLED_ShowString(20+2*6,20+cnt*14,":",12);
OLED_ShowxNum(20+3*6,20+cnt*14,sec[cnt],2,12,0x80,1);
OLED_ShowString(20+5*6,20+cnt*14,":",12);
OLED_ShowxNum(20+6*6,20+cnt*14,msec[cnt],2,12,0x80,1);
cnt++;
if(cnt>2)cnt=0;
}
}
//停止
else if(key==KEY2_PRESS)
{
oneflag=0;
TIM_Cmd(TIM3,DISABLE); //关闭定时器
sys_ctrl.min=0;sys_ctrl.sec=0;sys_ctrl.msec=0;
}
//返回
else if(key==KEY3_PRESS)
{
sys_ctrl.setmode=0;
sys_ctrl.min=0;sys_ctrl.sec=0;sys_ctrl.msec=0;
break;
}
//清除
else if(key==KEY4_PRESS)
{
sys_ctrl.min=0;sys_ctrl.sec=0;sys_ctrl.msec=0;
cnt=0;
OLED_Fill(20,20,20+8*6,60,0);
}
//秒表显示
OLED_ShowxNum(35,0,sys_ctrl.min,2,16,0x80,1);
OLED_ShowxNum(35+3*8,0,sys_ctrl.sec,2,16,0x80,1);
OLED_ShowxNum(35+6*8,4,sys_ctrl.msec,2,12,0x80,1);
OLED_Refresh_Gram();//刷新显存
}
}
//游戏过关判定
//返回1过关,0未过关
u8 game_pass(void)
{
u8 i=0,k=0;
for(i=0;i<MAP_ROW;i++)
{
for(k=0;k<MAP_COL;k++)
{
if(map[glevel][i][k]==BOX)
return 0;
}
}
return 1;
}
//游戏模式显示
void _game_mode_show(void)
{
OLED_Clear();//清屏
while(1)
{
//游戏过关
if(game_pass())
{
glevel++;
if(glevel>GAME_CENSOR)
{
//游戏通过
OLED_Clear();
OLED_ShowString(10,10,"Game Pass",16);
OLED_ShowString(10,30,"Reset Start",16);
OLED_Refresh_Gram();
while(1);
}
}
OLED_ShowFontHZ(X_WIDTH-40,10,21,16,1);//第
OLED_ShowNum(X_WIDTH-24,10,glevel+1,1,16);
OLED_ShowFontHZ(X_WIDTH-16,10,22,16,1);//关
game_draw();//游戏界面绘制
key_event();//按键消息处理
//两个键按下时则退出
if(KEY3==0 && KEY1==0)
{
delay_ms(10);
if(KEY3==0 && KEY1==0)
break;
}
}
}
//模式控制
void mode_ctrl(void)
{
if(sys_ctrl.set==1)//进入设置
{
switch(sys_ctrl.mode)
{
case 1:_set_mode_show();break;
case 2:break;
case 3:_game_mode_show();break;
case 4:_stopwatch_mode_show();break;
}
}
}
//应用控制系统
void app_sys_ctrl_demo(void)
{
u8 i=10;
LED_Init();
USART1_Init(115200);
OLED_Init();
KEY_Init();
BEEP_Init();
DS18B20_Init();
RTC_Init();
//获取稳定数据
while(i--)
{
sys_ctrl.temp=DS18B20_GetTemperture()*10;
delay_ms(100);
}
OLED_Init();
TIM4_Init(100,36000-1); //定时50ms
sys_parm_init();//系统参数初始化
while(1)
{
rtc_temp_show();//时钟温度显示
mode_switch_show();//模式选择显示
mode_ctrl();//模式控制
}
}
/*******************************************************************************
* 函 数 名 : TIM4_IRQHandler
* 函数功能 : TIM4中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void TIM4_IRQHandler(void)
{
static u8 cnt=0;
static u8 i=0;
if(TIM_GetITStatus(TIM4,TIM_IT_Update))
{
if(calendar.hour==sys_ctrl.alarm_time[0])
{
if(calendar.min==sys_ctrl.alarm_time[1])
{
sys_ctrl.alarm_flag=1;//闹钟到达
}
}
if(sys_ctrl.alarm_flag)
{
i++;
if(i%10==0)
{
BEEP_Alarm(50,100);
cnt++;
if(cnt>5)
{
cnt=0;sys_ctrl.alarm_flag=0;
}
}
}
}
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
}
/*******************************************************************************
* 函 数 名 : TIM3_IRQHandler
* 函数功能 : TIM3中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update))
{
sys_ctrl.msec++;
if(sys_ctrl.msec>=100)
{
sys_ctrl.msec=0;
sys_ctrl.sec++;
if(sys_ctrl.sec>59)
{
sys_ctrl.sec=0;
sys_ctrl.min++;
if(sys_ctrl.min>59)sys_ctrl.min=0;
}
}
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
三、实验现象
B站演示视频:https://space.bilibili.com/444388619
联系作者
专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。