标题:
STM32单片机rtc闹钟,旋钮,按键调节时间日期代码
[打印本页]
作者:
今天没吃饱
时间:
2024-7-4 22:41
标题:
STM32单片机rtc闹钟,旋钮,按键调节时间日期代码
#include "stm32f10x.h" // Device header
#include "Delay.h" //延时模块,主函数中未使用
#include "OLED.h" //OLED显示模块
#include "MyRTC.h" //RTC模块
#include "Key.h" //按键模块
#include "Buzzer.h" //蜂鸣器模块
#include "Encoder.h"
/*
功能: 简易时钟,可以通过按键调整日期时间和设定闹钟,通过OLED显示日期时间等相关信息
原理: RTC
接线: OLED显示屏:SCK接PB8,SDA接PB9
有源蜂鸣器(低电平触发):I/O接PB12
1~4号独立按键:分别接PB11,PB10,PB1,PB0
注意: 若出现没有现象或时间不动等情况,请查看MyRTC.c
*/
uint16_t MyRTC_Time[] = {2024,4,11,12,0,0}; //定义全局的时间数组,数组内容分别为年、月、日、时、分、秒
uint32_t Alarm_CNT,Alarm_Time,Alarm_Time_Rest; //闹钟相关变量,单位都是秒
uint8_t Hour,Min,Sec; //用来调整闹钟时间的变量
uint8_t KeyNum ; //按键键码值
uint8_t Flag_Count; //是否在计时标志,0为不在计时
uint8_t Flag_Change; //按键调节闹钟/日期/时间,0为调节闹钟,1为调节日期,2为调节时间
/*按键控制函数*/
void Key_Control(void)
{
KeyNum = Key_GetNum(); //读取按键键码
if(Flag_Change == 0) //调节闹钟
{
if(KeyNum == 1) //1号按键调整小时
{
Hour+= Encoder_Get();
if(Hour > 60)
Hour = 0;
}
else if(KeyNum == 2) //2号按键调整分钟
{
Min+= Encoder_Get();
if(Min > 60)
Min = 0;
}
else if(KeyNum == 3) //3号按键调整秒
{
Sec+= Encoder_Get();
if(Sec > 60)
Sec = 0;
}
else if(KeyNum == 4) //4号按键
{
if(Buzzer_State()==0) //若蜂鸣器没响
{
Alarm_Time = Hour*3600 + Min*60 + Sec; //计算闹钟时长,单位是秒
if(Alarm_Time > 0)
{
Alarm_CNT = RTC_GetCounter()+Alarm_Time-1; //设定闹钟值,需要-1
RTC_SetAlarm(Alarm_CNT); //写入闹钟值到RTC的ALR寄存器
Flag_Count = 1;
}
else //若闹钟时长为0,则转到按键调节日期
{
Flag_Change = 1;
}
}
else //若蜂鸣器响
{
Buzzer_OFF(); //关闭蜂鸣器
OLED_ShowString(4,1," "); //刷新oled第四行
}
}
}
else if(Flag_Change == 1) //调节日期
{
Delay_ms(2000);
KeyNum = Key_GetNum();
if(KeyNum == 1) //1号按键调整年
{
MyRTC_Time[0]+= Encoder_Get();
MyRTC_SetTime();
}
else if(KeyNum == 2) //2号按键调整月
{
MyRTC_Time[1]+= Encoder_Get();
MyRTC_SetTime();
}
else if(KeyNum == 3) //3号按键调整日
{
MyRTC_Time[2]+= Encoder_Get();
MyRTC_SetTime();
}
else if(KeyNum == 4) //4号按键,改为调整时间
{
Flag_Change = 2;
}
}
else if(Flag_Change == 2) //调节时间
{
Delay_ms(2000);
KeyNum = Key_GetNum();
if(KeyNum == 1) //1号按键调整小时
{
MyRTC_Time[3]+= Encoder_Get();
MyRTC_SetTime();
}
else if(KeyNum == 2) //2号按键调整分钟
{
MyRTC_Time[4]+= Encoder_Get();
MyRTC_SetTime();
}
else if(KeyNum == 3) //3号按键调整秒
{
MyRTC_Time[5]+= Encoder_Get();
MyRTC_SetTime();
}
else if(KeyNum == 4) //4号按键
{
Flag_Change = 0; //改为调整闹钟
OLED_ShowString(4,1," "); //刷新oled第四行
}
}
}
int main(void)
{
/*模块初始化*/
OLED_Init(); //OLED初始化
MyRTC_Init(); //RTC初始化
Key_Init(); //按键初始化
Buzzer_Init(); //蜂鸣器初始化
Encoder_Init(); //旋转编码器初始化
/*显示静态字符串*/
OLED_ShowString(1, 1, "Date:XXXX-XX-XX");
OLED_ShowString(2, 1, "Time:XX:XX:XX");
OLED_ShowString(3, 1, "Alarm:XX:XX:XX");
while (1)
{
MyRTC_ReadTime(); //RTC读取时间,最新的时间存储到MyRTC_Time数组中
Key_Control(); //调用按键控制函数
OLED_ShowNum(1, 6, MyRTC_Time[0], 4); //显示MyRTC_Time数组中的时间值,年
OLED_ShowNum(1, 11, MyRTC_Time[1], 2); //月
OLED_ShowNum(1, 14, MyRTC_Time[2], 2); //日
OLED_ShowNum(2, 6, MyRTC_Time[3], 2); //时
OLED_ShowNum(2, 9, MyRTC_Time[4], 2); //分
OLED_ShowNum(2, 12, MyRTC_Time[5], 2); //秒
OLED_ShowNum(4, 15, Key_GetNum(), 2); //秒
if(Flag_Count) //正在计时,则显示闹钟响起剩余时间
{
Alarm_Time_Rest = Alarm_CNT-RTC_GetCounter()+1; //计算闹钟响起剩余时间
if(Alarm_Time_Rest > Alarm_Time) //防止溢出错误
Alarm_Time_Rest = 0;
OLED_ShowNum(3,7,Alarm_Time_Rest/3600,2); //显示剩余小时
OLED_ShowNum(3,10,(Alarm_Time_Rest%3600)/60,2); //显示剩余分钟
OLED_ShowNum(3,13,(Alarm_Time_Rest%3600)%60,2); //显示剩余秒
if(RTC_GetFlagStatus(RTC_FLAG_ALR) == 1) //闹钟时间到,检查标志位为1
{
RTC_ClearFlag(RTC_FLAG_ALR); //清除标志位
Flag_Count = 0;Alarm_Time = 0; //重置相关参数
Hour = 0;Min = 0; Sec = 0;
Buzzer_ON(); //打开蜂鸣器
OLED_ShowString(4,1,"Time Out");
}
else //闹钟时间未到
{
OLED_ShowString(4,1,"Counting"); //显示正在计时
}
}
else //不在计时,则显示需要设定的闹钟时间
{
OLED_ShowNum(3,7,Hour,2);
OLED_ShowNum(3,10,Min,2);
OLED_ShowNum(3,13,Sec,2);
}
if(Flag_Change == 1) //显示“调节日期”
{
OLED_ShowString(4,1,"Change Date");
}
else if(Flag_Change == 2) //显示“调节时间”
{
OLED_ShowString(4,1,"Change Time");
}
}
}
复制代码
原理图: 无
仿真: 无
代码:
Project.7z
(187.52 KB, 下载次数: 24)
2024-7-4 23:46 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
触景情伤
时间:
2024-7-9 23:54
精度怎么样?
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1