This is the code used on my video series "Hybrid Supercapacitor Car Battery" for my own hardware monitoring system. THe videos can be found on madelectronengineering.com
Dependencies: BurstSPI Fonts INA219 mbed LPC1114_WakeInterruptIn
Fork of SharpMemoryLCD by
WakeUp_STM_RTC.cpp
00001 #ifdef TARGET_STM 00002 // added by JH1PJL 2017-9-21 00003 #if defined(TARGET_NUCLEO_F446RE) || defined(TARGET_NUCLEO_F411RE)\ 00004 || defined(TARGET_NUCLEO_F401RE)\ 00005 || defined(TARGET_NUCLEO_L152RE) || defined(TARGET_NUCLEO_L073RZ)\ 00006 || defined(TARGET_NUCLEO_L053R8) 00007 // use WakeUp_STM32_others.cpp 00008 #else 00009 00010 #include "WakeUp.h" 00011 #include "rtc_api.h" 00012 00013 #define BYTE2BCD(byte) ((byte % 10) | ((byte / 10) << 4)) 00014 00015 //Most things are pretty similar between the different STM targets. 00016 //Only the IRQ number the alarm is connected to differs. Any errors 00017 //with RTC_IRQn/RTC_Alarm_IRQn in them are related to this 00018 #if defined(TARGET_M4) || defined(TARGET_M3) 00019 #define RTC_IRQ RTC_Alarm_IRQn 00020 #else 00021 #define RTC_IRQ RTC_IRQn 00022 #endif 00023 00024 // Some things to handle Disco L476VG (and similar ones) 00025 #if defined(TARGET_STM32L4) 00026 #define IMR IMR1 00027 #define EMR EMR1 00028 #define RTSR RTSR1 00029 #define FTSR FTSR2 00030 #define PR PR1 00031 #endif 00032 00033 //Disabling the Backup Powerdomain does not seem to work nicely anymore if you want to use other RTC functions afterwards. 00034 //For now I have disabled it in code, if you find WakeUp increases your powerconsumption, try enabling it again (code is still there, just commented) 00035 00036 Callback<void()> WakeUp::callback; 00037 00038 void WakeUp::set_ms(uint32_t ms) 00039 { 00040 if (!rtc_isenabled()) { //Make sure RTC is running 00041 rtc_init(); 00042 wait_us(250); //The f401 seems to want a delay after init 00043 } 00044 00045 //PWR->CR |= PWR_CR_DBP; //Enable power domain 00046 RTC->WPR = 0xCA; //Disable RTC write protection 00047 RTC->WPR = 0x53; 00048 00049 //Alarm must be disabled to change anything 00050 RTC->CR &= ~RTC_CR_ALRAE; 00051 while(!(RTC->ISR & RTC_ISR_ALRAWF)); 00052 00053 if (ms == 0) { //Just disable alarm 00054 //PWR->CR &= ~PWR_CR_DBP; //Disable power domain 00055 RTC->WPR = 0xFF; //Enable RTC write protection 00056 return; 00057 } 00058 00059 //RTC prescaler + calculate how many sub-seconds should be added 00060 uint32_t prescaler = (RTC->PRER & 0x7FFF) + 1; 00061 uint32_t subsecsadd = ((ms % 1000) * prescaler) / 1000; 00062 00063 if ((ms < 1000) && (subsecsadd < 2)) 00064 subsecsadd = 2; //At least 2 subsecs delay to be sure interrupt is called 00065 00066 __disable_irq(); //At this point we don't want IRQs anymore 00067 00068 //Get current time 00069 uint32_t subsecs = RTC->SSR; 00070 time_t secs = rtc_read(); 00071 00072 //Calculate alarm values 00073 //Subseconds is countdown, so substract the 'added' sub-seconds and prevent underflow 00074 if (subsecs < subsecsadd) { 00075 subsecs += prescaler; 00076 secs++; 00077 } 00078 subsecs -= subsecsadd; 00079 00080 //Set seconds correctly 00081 secs += ms / 1000; 00082 struct tm *timeinfo = localtime(&secs); 00083 00084 //Enable rising edge EXTI interrupt of the RTC 00085 EXTI->IMR |= RTC_EXTI_LINE_ALARM_EVENT; 00086 EXTI->EMR &= ~RTC_EXTI_LINE_ALARM_EVENT; 00087 EXTI->RTSR |= RTC_EXTI_LINE_ALARM_EVENT; 00088 EXTI->FTSR &= ~RTC_EXTI_LINE_ALARM_EVENT; 00089 00090 //Calculate alarm register values 00091 uint32_t alarmreg = 0; 00092 alarmreg |= BYTE2BCD(timeinfo->tm_sec) << 0; 00093 alarmreg |= BYTE2BCD(timeinfo->tm_min) << 8; 00094 alarmreg |= BYTE2BCD(timeinfo->tm_hour) << 16; 00095 alarmreg |= BYTE2BCD(timeinfo->tm_mday) << 24; 00096 00097 //Enable RTC interrupt 00098 RTC->ALRMAR = alarmreg; 00099 RTC->ALRMASSR = subsecs | RTC_ALRMASSR_MASKSS; //Mask no subseconds 00100 RTC->CR |= RTC_CR_ALRAE | RTC_CR_ALRAIE; //Enable Alarm 00101 00102 RTC->WPR = 0xFF; //Enable RTC write protection 00103 //PWR->CR &= ~PWR_CR_DBP; //Disable power domain 00104 00105 __enable_irq(); //Alarm is set, so irqs can be enabled again 00106 00107 //Enable everything else 00108 NVIC_SetVector(RTC_IRQ, (uint32_t)WakeUp::irq_handler); 00109 NVIC_EnableIRQ(RTC_IRQ); 00110 } 00111 00112 00113 void WakeUp::irq_handler(void) 00114 { 00115 //Clear RTC + EXTI interrupt flags 00116 //PWR->CR |= PWR_CR_DBP; //Enable power domain 00117 RTC->ISR &= ~RTC_ISR_ALRAF; 00118 RTC->WPR = 0xCA; //Disable RTC write protection 00119 RTC->WPR = 0x53; 00120 RTC->CR &= ~RTC_CR_ALRAE; 00121 RTC->WPR = 0xFF; //Enable RTC write protection 00122 EXTI->PR = RTC_EXTI_LINE_ALARM_EVENT; 00123 //PWR->CR &= ~PWR_CR_DBP; //Disable power domain 00124 callback.call(); 00125 } 00126 00127 void WakeUp::calibrate(void) 00128 { 00129 //RTC, we assume it is accurate enough without calibration 00130 } 00131 00132 #endif // TARGET_NUCLEO_F446RE (added by JH1PJL 2017-9-21) 00133 #endif
Generated on Wed Jul 13 2022 09:15:42 by 1.7.2