首先,看一下stop模式下的说明:这是stm32l1xx 参考手册的说明,如果英文看不懂的话,可以查找stm32f10x的中文参考手册的说明看一下,意思差不多。
//RTC 时钟配置
void rtc_init(void) {
uint32_t timeout = 600000;
RTC_InitTypeDef RTC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the PWR clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
/* Allow access to RTC */
PWR_RTCAccessCmd(ENABLE);
RTC_WaitForSynchro();
/* Enable the LSE OSC */
RCC_LSEConfig(RCC_LSE_ON);
/* Wait till LSE is ready */
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {
timeout--;
if (timeout == 0)
break;
}
if (timeout == 0) {
RCC_LSICmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
;
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
} else {
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); /* Select the RTC Clock Source */
}
/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro(); /* Wait for RTC APB registers synchronisation */
/* Configure the RTC data register and RTC prescaler */
if (RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x32F2) { //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎
RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
RTC_InitStructure.RTC_SynchPrediv = 0xFF;
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);
RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);
}
RTC_WaitForSynchro();
/* RTC 唤醒中端配置: Clock Source: RTCDiv_16, Wakeup Time Base: 4s */
// RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div16); //这两句不需要
// RTC_SetWakeUpCounter(0x1FFF); //0x1FFF = 8191; 4s = (8191+1)*(1/(32768/16))
}
//RTC定时器A的配置
void platform_rtc_set_alarmA(void) {
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RTC_AlarmTypeDef RTC_AlarmStructure;
//非待机模式,RTC alarm timer中断配置及中断处理
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; //使能LINE17
EXTI_Init(&EXTI_InitStructure);
/* Enable the RTC Wakeup Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn; //RTC_Alarm_IRQn RTC_WKUP_IRQn
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
RTC_GetTime(RTC_Format_BIN, &RTC_AlarmStructure.RTC_AlarmTime);
//每月29号的上午8点定时器唤醒,也可以配制成按星期唤醒,如每周一的早上8点唤醒
RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours = 8; //小时
RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes = 0; //分钟
RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = 0;
RTC_AlarmStructure.RTC_AlarmTime.RTC_H12 = RTC_H12_AM;
RTC_AlarmStructure.RTC_AlarmDateWeekDay = 0x29;
RTC_AlarmStructure.RTC_AlarmDateWeekDaySel =
RTC_AlarmDateWeekDaySel_Date; //按日期, 也可以按星期几
RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay; //屏蔽星期和日期
RTC_AlarmCmd(RTC_Alarm_A, DISABLE); //关闭闹钟A,以便进行配置参数写入。
RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStructure);
RTC_AlarmCmd(RTC_Alarm_A, ENABLE); //开启闹钟A
RTC_ClearITPendingBit(RTC_IT_ALRA); //清除RTC闹钟A的标志
EXTI_ClearITPendingBit(EXTI_Line17); //清除LINE17上的中断标志位
}
//定时器唤醒处理中断。
void RTC_Alarm_IRQHandler(void) {
if (RTC_GetITStatus(RTC_IT_ALRA) != RESET) {
RTC_ClearITPendingBit(RTC_IT_ALRA);
EXTI_ClearITPendingBit(EXTI_Line17);
CHECK_VOL_FLAG = 1; //唤醒后置位检测电压的标志
}
}
定时每月28日的上午8点唤醒后,程序会从进入stop模式的下一句开始执行。
执行效果
int main(void) {
platform_rcc_init(); //SYSCLK,PLLCKL,HCLK,PCK1(APB1),PLK2(APB2)时钟初始化配置
rtc_init();
printf("Boot Initialization!\n");
SetRTC(75900, 191029, 2);
platform_rtc_set_alarmA();
while (1) {
printf("\r\nwhile begin!\n");
process_usart(); //对于串口命令的处理
updatetime();
printf("datetime:%02d-%02d-%02d %02d:%02d:%02d weakday:%d\n", year, mon,
day, hour, min, sec, wkday);
Sys_Standby();
}
}
void Sys_Standby(void) {
PWR_ClearFlag(PWR_FLAG_WU);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); //使能PWR外设时钟
printf("\r\n entry stop mode!\n ");
PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI); //进入stop模式
Usart1_Init(9600, USART_Parity_No, USART_WordLength_8b);
printf("\r\n WKUP_DELAY = %d!\n ",WKUP_DELAY);
}