LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

Obsługa RTC w STM32

 

List. 2

void Configuration_RTC(void)
{
    //włączenie dostępu do BKP
    PWR_BackupAccessCmd(ENABLE);
    //deinicjalizacja BPK
    BKP_DeInit();
    //wejście do trybu edycji RTC
    RTC_EnterConfigMode();
    //włączenie LSE
    RCC_LSEConfig(RCC_LSE_ON);
    //odczekanie na poprawne włączenie LSE
    while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){};
    //RTCCLK = LSE = 32768 Hz
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
    //włączenie zegara RTC
    RCC_RTCCLKCmd(ENABLE);
    //dczekanie na synchronizacje
    RTC_WaitForSynchro();
    //odczekanie na zakończenie operacji
    RTC_WaitForLastTask();
    //ustawienie preskalera na 32768 taktów
    RTC_SetPrescaler(32767);
    //odczekanie na zakończenie operacji
    RTC_WaitForLastTask();
    //wyjscie z trybu edycji
    RTC_ExitConfigMode();
    //ustawienie licznika RTC na 12h00m00s
    RTC_SetCounter(43200);
    //zresetowanie flagi SECF rejestru RTC->CRL, wymagane do poprawnego zapisu rejestru alarmu
    RTC_ClearFlag(RTC_FLAG_SEC);
    while(RTC_GetFlagStatus(RTC_FLAG_SEC) == RESET){};
    //odczekanie na zakończenie operacji na RTC
    RTC_WaitForLastTask();
    //ustawienie rejestru alarmu RTC na 12h00m00s
    RTC_SetAlarm(43200);
    //odczekanie na zakończenie operacji na RTC
    RTC_WaitForLastTask();
}

Funkcja Configuration_RTC przedstawia klasyczną inicjalizację zegara czasu rzeczywistego przy wykorzystaniu biblioteki dostarczonej przez firmę STMicroelectronics – STM32F10x_StdPeriph_Lib_V3.3.0. Dodatkowo funkcją void RTC_SetCounter(uint32_t CounterValue) są wprowadzane dane do licznika odpowiadającego za przechowywanie wartości odmierzanego czasu. Natomiast za pomocą funkcji void RTC_SetAlarm(uint32_t AlarmValue) są wprowadzane dane porównywane z licznikiem w celu wywołania alarmu. Wprowadzenie czasu alarmu jest realizowane, analogicznie do zmiany wartości licznika RTC. Operacja ta jest musi być poprzedzona wyczyszczeniem flagi SECF rejestru RTC->CRL.
W działaniu zegarka są wykorzystywane przerwania. W związku z tym należy je odpowiednio skonfigurować i zaimplementować funkcje obsługi przerwań. Na listingu 3 pokazano skróconą funkcję (o mniej istotne elementy) konfigurującą system przerwań.

 

List. 3

void Configuration_Interrupts(void)
{
    //zdefiniowanie struktury wykorzystywanej do konfiguracji przerwani
    NVIC_InitTypeDef NVIC_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;

    //skonfigurowanie miejsca przechowywania tablicy wektorów przerwań
    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

    //konfiguracja podziału priorytetów przerwań
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    //włączenie obsługi alarmu
    if(alarm_state == 1)
    {
        //konfiguracja przerwań pochodzących od RTC Alarm
        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;
        EXTI_Init(&EXTI_InitStructure);
        //generowanie przerwania przez RTC Alarm
        RTC_ITConfig(RTC_IT_ALR, ENABLE);
        //odczekanie na zakończenie operacji
        RTC_WaitForLastTask();
    }
    //wyłączenie obsługi alarmu
    else
    {
        //konfiguracja przerwań pochodzących od RTC Alarm
        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 = DISABLE;
        EXTI_Init(&EXTI_InitStructure);
        //generowanie przerwania przez RTC Alarm
        RTC_ITConfig(RTC_IT_ALR, ENABLE);
        //odczekanie na zakończenie operacji
        RTC_WaitForLastTask();
    }

    //konfiguracja przerwań pochodzących od RTC
    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    //generowanie przerwania przez RTC co 1s
    RTC_ITConfig(RTC_IT_SEC, ENABLE);
    //odczekanie na zakończenie operacji
    RTC_WaitForLastTask();

    //konfiguracja przerwań pochodzących od RTC Alarm
    NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    //konfiguracja obsługi przerwań od joysticka
    //. . .
    //konfiguracja obsługi przerwań od SysTick
//. . .
}

W programie są wykorzystywane dwa przerwania pochodzące od RTC. Pierwsze z nich to RTC_IT_SEC wywoływane przy każdej inkrementacji licznika RTC (w zależności od konfiguracji odpowiada to cyklicznemu wywołaniu co 1 sekundę). Drugie wykorzystywane przerwanie (RTC_IT_ALR) jest wywoływane, gdy następuje zgodność licznika z rejestrem przechowującym wartość do porównania, przerwanie określane jest jako alarm.
Konfiguracja przerwania RTC_IT_SEC polega na określeniu priorytetu i włączeniu obsługi przy wykorzystaniu funkcji z określonymi parametrami RTC_ITConfig(RTC_IT_SEC, ENABLE). W przypadku ustawień przerwania RTC_IT_ALR poza elementami analogicznymi do przerwania wywoływanego zmianą zawartości licznika RTC do poprawnej pracy należy dodatkowo skonfigurować linie przerwania. W dokumentacji Reference manual RM0008 można znaleźć informację, że zdarzenie alarmu RTC jest dołączone do linii 17 EXTI, tak więc musimy dokonać konfiguracji tego elementu. W funkcji jest to realizowane warunkowo w zależności od wartości zmiennej alarm_state (zmienna informująca czy  alarm jest włączony – 1, czy może jest wyłączony – 0).
W programie są obsługiwane przerwania pochodzące od różnych układów peryferyjnych. Są to przerwania wywoływane zmianą położenia joysticka, przerwania pochodzące od RTC (inkrementacja licznika oraz alarm) oraz przerwanie SysTick.
W przypadku obsługi przerwania od zmiany położenia joysticka, funkcja obsługi przerwania ma za zadanie zmienić aktualnie edytowany element oraz odpowiednio inkrementować lub dekrementować jego wartość – są to operacje typowo „matematyczne”.
Przerwanie SysTick wykorzystano do generowania dźwięku. Podyktowane to było tym, iż generowany sygnał nie musi być zbyt skomplikowany, a jedynie „drażniący”, by wymusić zauważenie włączenie alarmu. Operacje realizowane w przerwaniu przedstawiono na listingu 4. Można zauważyć, że jest to tylko przełączanie sygnału wyprowadzonego na przetwornik piezoceramiczny z odpowiednią częstotliwością (ustawioną w konfiguracji przerwania SysTick) realizowane warunkowo, gdy  nastąpi włączenie się alarmu.