Три дня ломал мозг над RTC в STM32L151 , и наконец у меня всё получилось !
Выкладываю свой код для Keil, т.к. других тем про RTC тут не нашёл.
RTC какой-то очень привередлевый. Ньюансы вроде того что в регистр PRER нужно сделать ровно две записи , причём сначала младшие биты потом старшие,
то что регистры с датой и временем можно записать только таким же образом , то что системная частота должна быть в более чем 7 раз больше частоты таймера
в документации написаны.
Почему в начале обязательно нужно сбросить настройки таймера которые и так сброшены при запуске МК , а без этого таймер инициализируется и работает но прерывания не происходит , я так и не понял.
Код
////////////////////////////// Настраиваем RTC часы/////////////////////////////////////
void RTC_INIT(system_time__ system_time)
{
int RTC_DR_MASK=0;
int RTC_TR_MASK=0;
RCC->CSR|=RCC_CSR_RTCRST; //
RCC->CSR&=~RCC_CSR_RTCRST; // сбросили настройки RTC
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_DBP;
RCC->CSR |= RCC_CSR_LSEON; //включили генератор LSE 32768
while(!(RCC->CSR & RCC_CSR_LSERDY)){} //ждём пока включится
RCC->CSR|=RCC_CSR_RTCEN; //включили RTC
RCC->CSR|=RCC_CSR_RTCSEL_LSE; // подаём тактовую частоту LSE на RTC
RTC->WRP=0xCA;
RTC->WRP=0x53; //отключаем защиту
if(!(RTC->ISR & RTC_ISR_INITF))//если таймер ещё не в режиме инициализации
{
RTC->ISR|=RTC_ISR_INIT;
while(!(RTC->ISR & RTC_ISR_INITF)){}//входим в режим инициализации
}
RTC->PRER=255;
RTC->PRER|=(127<<16);// устанавливаем делители, обязательно двумя записями.
RTC_TR_MASK|=(system_time.minute%10)<<8; // единицы минут
RTC_TR_MASK|=(system_time.minute/10)<<12; //есятки минут
RTC_TR_MASK|=(system_time.hour%10)<<16; //единицы часов
RTC_TR_MASK|=(system_time.hour/10)<<20; //десятки часов
RTC->TR=RTC_TR_MASK; //устанавливаем время
RTC_DR_MASK|=(system_time.day%10)<<0; //единицы дней
RTC_DR_MASK|=(system_time.day/10)<<4; // десятки дней
RTC_DR_MASK|=(system_time.months%10)<<8; //единицы месяцев
RTC_DR_MASK|=(system_time.months/10)<<12; // десятки месяцев
RTC_DR_MASK|=((system_time.year-2000)%10)<<16; //единицы годов
RTC_DR_MASK|=((system_time.year-2000)/10)<<20; //десятки годов
RTC->DR=RTC_DR_MASK; //устанавливаем дату
RTC->CR|=RTC_CR_WUTE; // включили wakup таймер
RTC->WUTR=0xFFFF;
RTC->CR&=~RTC_CR_WUCKSEL_1;
RTC->CR&=~RTC_CR_WUCKSEL_1;
RTC->CR&=~RTC_CR_WUCKSEL_2; // выбрали для waikup таймера частоту LSE/16
RTC->CR|=RTC_CR_WUTIE; // разрешили прерывание от wakup таймера
EXTI->IMR |= (1<<20); // прерывание EXTI line 20
EXTI->RTSR |= (1<<20); //по переднему фронту
NVIC_SetPriority(RTC_WKUP_IRQn, 5);
NVIC_EnableIRQ(RTC_WKUP_IRQn);
RTC->ISR&=~RTC_ISR_INIT; // выходим из режима инициализации.
}
////////////////////////прерывание wakup от RTC////////////////////////////////
void RTC_WKUP_IRQHandler(void)
{
EXTI->PR|=(1<<20); //
RTC->ISR&=~RTC_ISR_WUTF; //сбрасываем флаг прерывания
return;
}