S hrůzou jsem zjistil, že se nám nějak ztratil 32 díl seriálu o Discovery kitu. Díl pojednává o použití RTC, tedy hodin reálného času. Ukazuje jak řešit komunikaci s pomaloběžnými hodinami, které jsou integrovány v STM32F Value Line.


Úvodem

RTC je řešen dost nešikovně z hlediska programátora. Jde o jeden velký čítač, který se obvykle nastaví tak, aby se aktualizoval každou sekundu.
Doporučuji se podívat na aplikační poznámku ST, kterou naleznete zde. Je poměrně podrobně zpracována. Ale nejlepší je, že k Aplikační poznámce je přiložen i kód, který nám spoustu otravné práce ušetří. Naleznete jej v zip archívu zde.
Majitele kitu STM32L Discovery a STM32F4 Discovery předem uklidním, že oni mají situaci jednodušší, neboť jejich mcu na kitu obsahuje rozdělené čítače, takže nemusí nic složitě přepočítávat.


Program

Jak inicializujeme RTC:
 // pustime hodiny
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  // Povolime si pristup do BKP
  PWR_BackupAccessCmd(ENABLE);

  // Zresetujeme backupovane registry
  BKP_DeInit();

  // RTC hodiny vychazeji z frekvence HSE/128 = 62.5 kHz!
  //RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128);

  // RTC hodiny vychazeji z frekvence interního oscilátoru
  //RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);


  // RTC hodiny vychazeji z frekvence externiho oscilátoru 32 KHz

  // povolime LSE oscilator
  RCC_LSEConfig(RCC_LSE_ON);

  // pockame na spusteni oscilatoru 32kHz
  while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

  // nyni muzeme priradit hodinam jako zdroj kmitoctu LSE oscilator
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

  // povolime vstup kmitocku do RTC
  RCC_RTCCLKCmd(ENABLE);
  // Cekej na synchronizaci
  RTC_WaitForSynchro();
  // Pockame na dokonceni zapisu
  RTC_WaitForLastTask();

  // Nastavime typ alarmu
  // Alarm po 1 sek by se nastavil: RTC_ITConfig(RTC_IT_SEC, ENABLE);
  RTC_ITConfig(RTC_IT_ALR, ENABLE);
  // Pockame na dokonceni zapisu
  RTC_WaitForLastTask();

  // Nastavime spravnou rychlost hodin
  //RTC_SetPrescaler(62499); // pro HSE
  RTC_SetPrescaler(32767); // pro LSE
  // Pockame na dokonceni zapisu
  RTC_WaitForLastTask();
 


Jak nastavíme hodiny správně
uint32_t Time_Setup(void)
{
  uint32_t Tmp_HH = 0xFF, Tmp_MM = 0xFF, Tmp_SS = 0xFF;

  printf("\r\n  Please Set Hours");

  while (Tmp_HH == 0xFF)
  {
    Tmp_HH = USART_Scanf(23);
  }
  printf(":  %d", Tmp_HH);
  printf("\r\n  Please Set Minutes");
  while (Tmp_MM == 0xFF)
  {
    Tmp_MM = USART_Scanf(59);
  }
  printf(":  %d", Tmp_MM);
  printf("\r\n  Please Set Seconds");
  while (Tmp_SS == 0xFF)
  {
    Tmp_SS = USART_Scanf(59);
  }
  printf(":  %d", Tmp_SS);

  /* Return the value to store in RTC counter register */
  return((Tmp_HH*3600 + Tmp_MM*60 + Tmp_SS));
}


Pozor, že před nastavením musíme nechat RTC, aby dokončil co dělá.
void Nastav_Cas(void)
{
  RTC_WaitForLastTask();
  RTC_SetCounter(Time_Setup());
  RTC_WaitForLastTask();
}



Jak vydolujeme z RTC čítače aktuální čas:
CasTick = RTC_GetCounter();
Strcpy (T_Buff, "\nStisk T, Cas je ");
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
Strcpy (T_Buff, IntToStr (CasTick / 3600)) ;
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);   // povolime preruseni
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
Strcpy (T_Buff, " hodin ");
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
Strcpy (T_Buff, IntToStr ((CasTick % 3600) / 60));
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);   // povolime preruseni
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
Strcpy (T_Buff, " minut a ");
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
Strcpy (T_Buff, IntToStr ((CasTick % 3600) % 60));
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);   // povolime preruseni
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
Strcpy (T_Buff, " sekund   \n\r");      // nastavime co se odesle po USART
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);   // povolime preruseni
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
 


Jak nastavíme aktuální hodnotu správného času:
RTC_SetCounter(SpravnyCas);



Závěr

Raději upozorním, že novější typy (STM32L, STM32F2xx a STM32F4xx) mají RTC řešený lépe. Rozdíl je v tom, že řada STM32F1xx má jeden čítač (counter) ze kterého musíme časové údaje vypočítat, ale nové řešení obsahuje oddělené čítače obsahující časové údaje. Tudíž je obsluha jednodušší a snadnější. Nicméně čipy Value Line jsou velmi levné a proto se používají často a je dobré vědět jak řešit otázku RTC i u tohoto typu ARM mcu. Výhodou RTC obecně je, že běží na napájení ze zálohovacího zdroje, tedy i v případě vypadnutí hlavního napájení mcu nám zůstává při využití RTC, čas aktualizovaný a správný. Pro řešení nějakého sběru dat časově závislých (např. meteorologická stanice) je použití RTC nezbytností.


Odkazy

STM32-VL DISCOVERY popis je zde.
STM32-VL Discovery 2. (další popis, osobní poznatky) je zde.
Začínáme s STM32 VL Discovery kitem naleznete zde.
Začínáme s STM32 VL Discovery kitem _2. naleznete zde.
Začínáme s STM32 VL Discovery kitem _3. naleznete zde.
Začínáme s STM32 VL Discovery kitem _4. naleznete zde.
Začínáme s STM32 VL Discovery kitem _5. naleznete zde.
Začínáme s STM32 VL Discovery kitem _6. naleznete zde. (blikání LED)
Začínáme s STM32 VL Discovery kitem _7. naleznete zde. (ladění)
Začínáme s STM32 VL Discovery kitem _8. naleznete zde. (využití SysTick)
Začínáme s STM32 VL Discovery kitem _9. naleznete zde. (změna CLK)
Začínáme s STM32 VL Discovery kitem 10. naleznete zde. (kontaktní pole)
Začínáme s STM32 VL Discovery kitem 11. naleznete zde. (PWM)
Začínáme s STM32 VL Discovery kitem 12. naleznete zde. (watchdog)
Začínáme s STM32 VL Discovery kitem 13. naleznete zde. (externí přerušení)
Začínáme s STM32 VL Discovery kitem 14. naleznete zde. (LCD)
Začínáme s STM32 VL Discovery kitem 15. naleznete zde. (ADC)
Začínáme s STM32 VL Discovery kitem 16. naleznete zde. (Teplotní čidlo)
Začínáme s STM32 VL Discovery kitem 17. naleznete zde. (klávesnice PS/2)
Začínáme s STM32 VL Discovery kitem 18. naleznete zde. (správná verze LCD.c)
Začínáme s STM32 VL Discovery kitem 19. naleznete zde. (DAC převodník)
Začínáme s STM32 VL Discovery kitem 20. naleznete zde. (DAC s přerušením)
Začínáme s STM32 VL Discovery kitem 21. naleznete zde. (DMA v paměti)
Začínáme s STM32 VL Discovery kitem 22. naleznete zde. (DMA s DAC)
Začínáme s STM32 VL Discovery kitem 23. naleznete zde. (RTC)
Dodatek k "Začínáme s STM32 VL Discovery kitem 23." je zde. (RTC úprava)
Začínáme s STM32 VL Discovery kitem 24. naleznete zde. (RTOS-přehled)
Začínáme s STM32 VL Discovery kitem 25. naleznete zde. (USART-přerušení)
Začínáme s STM32 VL Discovery kitem 26. naleznete zde. (USART-přesměrování vstupů a výstupů)
Začínáme s STM32 VL Discovery kitem 27. naleznete zde. (Assembler vkládaný do C kódu)
Začínáme s STM32 VL Discovery kitem 28. naleznete zde. (Vnořované přerušení)
Začínáme s STM32 VL Discovery kitem 29. naleznete zde. (Přímé řízení znakového LCD)
Začínáme s STM32 VL Discovery kitem 30. naleznete zde. (I2C komunikace)
Začínáme s STM32 VL Discovery kitem 31. naleznete zde. (mcu řady STM32L)

Definice konektorů STM VL Discovery kitu v Eagle pro vytvoření projektu
s konektorem, do něhož jde zasunout kit naleznete zde.
Jak na STM VL Discovery s programovým vybavením od Keil 1. je zde.
Jak na STM VL Discovery s programovým vybavením od Keil 2. je zde.
Jak zprovoznit STM VL Discovery pokud si při pokusech zakážete JTAG piny pomocí bootloaderu je zde.

Reference manuál k Value Line naleznete zde.

Zazipovaný zdrojový kód k tomuto projektu naleznete zde.