Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: RTC STM32L151 прерывание
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
MiklPolikov
Три дня ломал мозг над 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;
}
Apparatchik
А у меня никак не выходит. Контроллер STM32L152RBT6 виснет (перестает срабатывать прерывание от SysTick). Что-то я упустил.
hd44780
Цитата(Apparatchik @ Dec 24 2012, 17:25) *
Контроллер STM32L152RBT6 виснет (перестает срабатывать прерывание от SysTick). Что-то я упустил.


С данным процом я не работал, но пытался сделать такое на AT91SAM7S256 (ядро ARM7TDMI). Там есть PIT (аналог Вашего SysTick) и RTC. Когда пытался включить оба разом - всё висло.
Оказалось, что оба они, грубо говоря, висят на одном прерывании (как я понял, у меня архитектура такая), и использовать их можно только по одному - или тот или другой. Может и я в чём-то неправ, не знаю.

В итоге сделал часики на отдельном таймере общего назначения biggrin.gif . Работает как часы laughing.gif .
Может и у Вас что-то родственное.
Apparatchik
Если обработчик прерывания один на несколько событий, то нужно проверять флаги в регистрах статуса всех событий, которые могут вызвать этот обработчик, выполнять нужное действия в зависимости от того, кто вызвал и сбрасывать флаг. По крайней мере так я понял по поводу STM32.

Часы я вроде запустил, но вроде в даташите упоминалось что они продолжают идти после системного зброса. Апаратный сброс кнопкой RESET должен их сбрасывать? у меня они идут сначала.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.