Files
2026-04-23 10:50:18 +08:00

490 lines
14 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "rtc.h"
//平年的月份日期表 闰年2月份29天
const u8 mon_table[12]={31,28,31,30,31,30,31,31,30,31,30,31};
MYITStatus_Struct MYITStatus1;
// u8 time[3]={0};
void NVIC_EXTI_CONFIG(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;
GPIO_Init(GPIOC,&GPIO_InitStructure);
//enable syscfg clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
// connect EXTI10 line to PA0 pin
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource13);
EXTI_ClearITPendingBit(EXTI_Line13);
EXTI_InitStructure.EXTI_Line=EXTI_Line13;//RTC wakeup
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00;
NVIC_Init(&NVIC_InitStructure);
}
void RTC_NVIC_CONFIG(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN;
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_DOWN;
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_PinAFConfig(GPIOC,GPIO_PinSource13,GPIO_AF_WKUP);
EXTI_ClearITPendingBit(EXTI_Line20);
EXTI_InitStructure.EXTI_Line=EXTI_Line20;//RTC wakeup
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel=RTC_WKUP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00;
NVIC_Init(&NVIC_InitStructure);
/* EXTI configuration */
EXTI_ClearITPendingBit(EXTI_Line17);
EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Enable the RTC Alarm Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void RTC_Time_Init(void)
{
RTC_InitTypeDef RTC_InitStructure;
//RTC_TimeTypeDef RTC_TimeStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
/*!< Allow access to RTC */
PWR_RTCAccessCmd(ENABLE);
/*!< 使能外部低速时钟 */
RCC_LSEConfig(RCC_LSE_ON);
// RCC_LSICmd(ENABLE);
/*!< 等待外部低速时钟就绪 */
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//选择外部LES作为RTC时钟源
RCC_RTCCLKCmd(ENABLE);
/*!< Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();
RTC_InitStructure.RTC_AsynchPrediv=127;
RTC_InitStructure.RTC_HourFormat=RTC_HourFormat_24;
RTC_InitStructure.RTC_SynchPrediv=255;
RTC_Init(&RTC_InitStructure);//RTC的时钟1HZ
RTC_NVIC_CONFIG();
}
void rtc_std_init(void)
{
/* Enable the PWR clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
/* Allow access to RTC */
PWR_RTCAccessCmd(ENABLE);
/* Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();
}
//设置本地硬件RTC时间
void SetRTC(int set_year,int set_mon,int set_day,int set_hour,int set_min ,int set_sec)
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
RTC_TimeStruct.RTC_Hours = set_hour;
RTC_TimeStruct.RTC_Minutes = set_min;
RTC_TimeStruct.RTC_Seconds = set_sec;
RTC_TimeStruct.RTC_H12 = 0; //程序中不使用上午/下午
RTC_SetTime(RTC_Format_BIN,&RTC_TimeStruct);
RTC_DateStruct.RTC_Year = set_year;
RTC_DateStruct.RTC_Month = set_mon;
RTC_DateStruct.RTC_Date = set_day;
RTC_DateStruct.RTC_WeekDay = 1;//程序中不使用星期
RTC_SetDate(RTC_Format_BIN,&RTC_DateStruct);
// RTC_WaitForSynchro();
RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);
}
void Set_GNSSTIME_Rtc(void)
{
int set_years, set_mons, set_days, set_hours, set_mins , set_secs;
if(Save_Data.isUsefull)//定位数据有效
{
set_years=(Save_Data.UTCData[0]-'0')*10+(Save_Data.UTCData[1]-'0');//年
set_mons=(Save_Data.UTCData[2]-'0')*10+(Save_Data.UTCData[3]-'0');//月
set_days=(Save_Data.UTCData[4]-'0')*10+(Save_Data.UTCData[5]-'0');//日
set_hours=(Save_Data.UTCTime[0]-'0')*10+(Save_Data.UTCTime[1]-'0')+8;//时
set_mins=(Save_Data.UTCTime[2]-'0')*10+(Save_Data.UTCTime[3]-'0');//分
set_secs=(Save_Data.UTCTime[4]-'0')*10+(Save_Data.UTCTime[5]-'0');//秒
SetRTC(set_years,set_mons,set_days,set_hours,set_mins,set_secs);
}
}
//获取本地硬件RTC时间
void GetRTC(char *hhmmss,char *yymmdd)
{
RTC_TimeTypeDef time;
RTC_DateTypeDef date;
RTC_GetTime(RTC_Format_BIN,&time);
RTC_GetDate(RTC_Format_BIN,&date);
yymmdd[0]=date.RTC_Year/10+0x30; //年十位
yymmdd[1]=date.RTC_Year%10+0x30; //年个位
yymmdd[2]=date.RTC_Month/10+0x30; //月十位
yymmdd[3]=date.RTC_Month%10+0x30; //月十位
yymmdd[4]=date.RTC_Date/10+0x30; //日十位
yymmdd[5]=date.RTC_Date%10+0x30; //日十位
hhmmss[0]=time.RTC_Hours/10+0x30; //小时十位
hhmmss[1]=time.RTC_Hours%10+0x30; //小时个位
hhmmss[2]=time.RTC_Minutes/10+0x30; //分钟十位
hhmmss[3]=time.RTC_Minutes%10+0x30; //分钟十位
hhmmss[4]=time.RTC_Seconds/10+0x30; //秒十位
hhmmss[5]=time.RTC_Seconds%10+0x30; //秒十位
}
u32 RTC_GetSeconds(void)
{
u32 secondss;
RTC_TimeTypeDef time;
RTC_GetTime(RTC_Format_BIN,&time);
secondss= time.RTC_Hours*3600 + time.RTC_Minutes*60 + time.RTC_Seconds;
return secondss;
}
void RtcWakeUpConfig(u32 temp)
{
RTC_NVIC_CONFIG();
RTC_WakeUpCmd(DISABLE);
RTC_ClearFlag(RTC_FLAG_WUTF);
if(temp>65535)RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_17bits);
else RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);
RTC_SetWakeUpCounter(temp); //设置唤醒时间--S,最大65536s=18小时 2^17=131072 131072/3600s=36.4h
RTC_ClearITPendingBit(RTC_IT_WUT);
RTC_ITConfig(RTC_IT_WUT,ENABLE); //需要使能中断,不需要中断函数
RTC_WakeUpCmd(ENABLE);
}
//判断是否是闰年函数
//月份 1 2 3 4 5 6 7 8 9 10 11 12
//闰年 31 29 31 30 31 30 31 31 30 31 30 31
//非闰年 31 28 31 30 31 30 31 31 30 31 30 31
//输入:年份
//输出:该年份是不是闰年.1,是.0,不是
u8 Is_Leap_Year(u16 year)
{
year=year+2000;
// year=0x14ff&year;
if(year%4==0) //必须能被4整除
{
if(year%100==0)
{
if(year%400==0)return 1;//如果以00结尾,还要能被400整除
else return 0;
}else return 1;
}else return 0;
}
void MYRTC_Init(void)
{
RTC_NVIC_CONFIG();
RTC_Time_Init();
PWR_ClearFlag(PWR_FLAG_WU);//唤醒之后加上这个清除中断
}
void RTC_AlarmAConfig(u32 seconds)
{
int month_day;
RTC_TimeTypeDef nowtimes;
RTC_DateTypeDef nowdatas;
RTC_AlarmTypeDef RTC_AlarmStructure;
RTC_ClearFlag(RTC_FLAG_ALRAF);
RTC_ClearITPendingBit(RTC_IT_ALRA);
RTC_AlarmCmd(RTC_Alarm_A, DISABLE);
RTC_GetTime(RTC_Format_BIN,&nowtimes);//获取时间
RTC_GetDate(RTC_Format_BIN,&nowdatas);//获取日期
month_day=mon_table[nowdatas.RTC_Month-1];//获取月的天数
if(nowdatas.RTC_Month==2)
{
if(!Is_Leap_Year(nowdatas.RTC_Year))//闰年
month_day+=1; //二月份天数-1
}
seconds+=nowtimes.RTC_Hours*3600+nowtimes.RTC_Minutes*60+nowtimes.RTC_Seconds+nowdatas.RTC_Date*86400;
if((seconds/86400)>month_day)//判断是否超过本月份的天数
{
month_day=(seconds/86400)-month_day;
RTC_AlarmStructure.RTC_AlarmDateWeekDay = month_day;
}else
RTC_AlarmStructure.RTC_AlarmDateWeekDay = seconds/86400; //日
/* Set the alarmA Masks */
RTC_AlarmStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_None; //无屏蔽
/* Set the alarmA time */
RTC_AlarmStructure.RTC_AlarmTime.RTC_H12=RTC_H12_AM; //24H
RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours=(seconds%86400)/3600;//时
RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes=(seconds%86400)%3600/60;//分
RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds=(seconds%86400)%3600%60;//秒
RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStructure);
/* Enable AlarmA interrupt */
RTC_ITConfig(RTC_IT_ALRA, ENABLE);
/* Enable the alarmA */
RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
}
//闹钟B配置
void RTC_AlarmBConfig(int set_year,int set_mon,int set_day,int set_hour,int set_min ,int set_sec)
{
RTC_AlarmTypeDef RTC_AlarmStructure;
RTC_ClearFlag(RTC_FLAG_ALRBF);
RTC_ClearITPendingBit(RTC_IT_ALRB);
RTC_AlarmCmd(RTC_Alarm_B, DISABLE);
/* Set the alarmB Masks */
RTC_AlarmStructure.RTC_AlarmDateWeekDay = set_day;//日1-31
RTC_AlarmStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date; //选择日期
RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_None; //无屏蔽
/* Set the alarmB time */
RTC_AlarmStructure.RTC_AlarmTime.RTC_H12=RTC_H12_AM; //24H
RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours=set_hour;
RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes=set_min;
RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds=set_sec;
RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_B, &RTC_AlarmStructure);
/* Set AlarmA subseconds and enable SubSec Alarm : generate 8 interripts per Second */
// RTC_AlarmSubSecondConfig(RTC_Alarm_A, 0xFF, RTC_AlarmSubSecondMask_SS14_5);
/* Enable AlarmA interrupt */
RTC_ITConfig(RTC_IT_ALRB, ENABLE);
/* Enable the alarmA */
RTC_AlarmCmd(RTC_Alarm_B, ENABLE);
}
/*************检查设备唤醒源******************/
STB_ITStatus Get_Wkup_MYITstatus(void)
{
if(RTC_GetITStatus(RTC_IT_ALRA))
{
EXTI_ClearITPendingBit(EXTI_Line17);
RTC_ClearITPendingBit(RTC_IT_ALRA);
MYITStatus1.AlarmA_ITStatus=1;
// return AlarmA_ITHP;
}
if(RTC_GetITStatus(RTC_IT_ALRB))
{
EXTI_ClearITPendingBit(EXTI_Line17);
RTC_ClearITPendingBit(RTC_IT_ALRB);
MYITStatus1.AlarmB_ITStatus=1;
//return AlarmB_ITHP;
}
if(RTC_GetITStatus(RTC_IT_WUT))
{
EXTI_ClearITPendingBit(EXTI_Line20);
RTC_ClearITPendingBit(RTC_IT_WUT);
MYITStatus1.WUT_ITStatus=1;
//return WUT_ITHP;
}
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13))
{
delay_ms(2000);
if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13))
{
EXTI_ClearITPendingBit(EXTI_Line20);
MYITStatus1.WKUP1_ITStatus=1;
// return WKUP1_ITHP;
}
}
if(MYITStatus1.AlarmA_ITStatus | MYITStatus1.AlarmB_ITStatus | MYITStatus1.WUT_ITStatus | MYITStatus1.WKUP1_ITStatus)
{
if(MYITStatus1.AlarmA_ITStatus)return AlarmA_ITHP;
if(MYITStatus1.AlarmB_ITStatus)return AlarmA_ITHP;
if(MYITStatus1.WUT_ITStatus)return AlarmA_ITHP;
if(MYITStatus1.WKUP1_ITStatus)return AlarmA_ITHP;
}
else
{
MYITStatus1.WKUP_POWBUTTON=1;//电源上电
return Power_ON;
}
return Power_ON;
}
/**
* @brief This function handles RTC Alarm interrupt (A and B) request.
* @param None
* @retval None
*/
void RTC_Alarm_IRQHandler(void)
{
/* Check on the AlarmA falg and on the number of interrupts per Second (60*8) */
if(RTC_GetITStatus(RTC_IT_ALRA) != RESET)
{
/* Clear RTC AlarmA Flags */
RTC_ClearITPendingBit(RTC_IT_ALRA);
MYITStatus1.AlarmA_ITStatus=1;
RTC_AlarmCmd(RTC_Alarm_A, DISABLE);
u5_printf("alarmA hp\r\n");
}
/* Check on the AlarmA falg and on the number of interrupts per Second (60*8) */
if(RTC_GetITStatus(RTC_IT_ALRB) != RESET)
{
/* Clear RTC AlarmB Flags */
RTC_ClearITPendingBit(RTC_IT_ALRB);
RTC_AlarmCmd(RTC_IT_ALRB, DISABLE);
MYITStatus1.AlarmB_ITStatus=1;
}
/* Clear the EXTIL line 17 */
EXTI_ClearITPendingBit(EXTI_Line17);
}
void RTC_WKUP_IRQHandler(void)
{
if(RTC_GetITStatus(RTC_IT_WUT) != RESET)
{
RTC_ClearITPendingBit(RTC_IT_WUT);
RTC_WakeUpCmd(DISABLE);
EXTI_ClearITPendingBit(EXTI_Line20);
MYITStatus1.WUT_ITStatus=1;
u5_printf("WUT hp\r\n");
u5_printf("wut_PROS1_RUN:%d\r\n",TASKRUNSS.PROS1_RUN);
}
}
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line13) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line13);
MYITStatus1.WKUP1_ITStatus=1;
u5_printf("WAKEUP2 is HP");
}
}
u8 Check_WKUP(void)
{
// u8 t=0; //记录按下的时间
// while(WKUP_KD)
// {
// t++; //已经按下了
// delay_ms(100);
// if(t>=100) //按下超过10秒钟
// {
// return 1; //按下10s以上了
// }
// }
// if(t>10)return 2; //按下3s以上了
// else return 0;
if(WKUP_KD)return 1;
return 0;
}
/**
* 单个按键检测短按和长按事件
* 短按:时间 10ms < T < 1 s, 长按:时间 T >1 s
* 功能使用状态机方式扫描单个按键扫描周期为10ms,10ms刚好跳过抖动
* 状态机使用switch case语句实现状态之间的跳转
* lock变量用于判断是否是第一次进行按键确认状态
* :长按键事件提前执行,短按键事件释放后才执行
*/
u8 Key_Scan(void)
{
static KEY_STATE KeyState =KEY_CHECK;
static u8 TimeCnt = 0;
u8 key_return = 0;
switch (KeyState)
{
//按键未按下状态此时判断WKUP_KD的值
case KEY_CHECK:
if(WKUP_KD)
{
KeyState = KEY_COMFIRM; //如果按键WKUP_KD值为1说明按键开始按下进入下一个状态
}
else
{
KeyState = KEY_CHECK;
}
TimeCnt = 0; //计数复位
key_return=0;
break;
case KEY_COMFIRM:
if(WKUP_KD) //查看当前WKUP_KD是否还是1再次确认是否按下
{
TimeCnt++;
if(TimeCnt>=200)TimeCnt=200;
}
else
{
KeyState = KEY_RELEASE; // 返回上一个状态
}
break;
case KEY_RELEASE:
if(!WKUP_KD) //当前WKUP_KD值为0说明按键已经释放返回开始状态
{
KeyState = KEY_CHECK;
if(TimeCnt>10 ) key_return = KEY_SHORT;
if(TimeCnt>100) key_return = KEY_LONG;
u5_printf("TimeCnt:%d\r\n",TimeCnt);
}
break;
default: break;
}
return key_return;
}