Forum: Mikrocontroller und Digitale Elektronik STM32F103 habe ich die RTC richtig initialisiert?


von Stefan F. (Gast)


Lesenswert?

Ich bin noch bei meinen ersten Versuchen, den STM32F103RBT6 (auf einem 
Nucleo-64 Board) zu programmieren. Ich möchte ohne HAL nur auf Basis der 
CMSIS die LED an PA5 exakt im Sekundentakt blinken lassen. Dazu verwende 
ich die RTC, während der Systemtakt vom internen R/C Oszillator kommt.

Die LED blinkt wie gewünscht im Sekundentakt. Ich wüsste gerne, ob ich 
es richtig im Sinne der CMSIS gemacht habe:
1
#include "stm32f1xx.h"
2
3
4
void RTC_Handler(void)
5
{
6
    // Toggle LED at PA5
7
    GPIOA->ODR ^= GPIO_ODR_ODR5;
8
9
    // Clear interrupt flag
10
    CLEAR_BIT(RTC->CRL,RTC_CRL_SECF);
11
}
12
13
14
void initRtc()
15
{
16
    // Enable the backup domain
17
    SET_BIT(RCC->APB1ENR, RCC_APB1ENR_BKPEN + RCC_APB1ENR_PWREN);
18
19
    // Enable write access to the backup domain
20
    SET_BIT(PWR->CR, PWR_CR_DBP);
21
22
    // Enable LSE oscillator
23
    SET_BIT(RCC->BDCR, RCC_BDCR_LSEON);
24
25
    // Wait until LSE oscillator is ready
26
    while(!READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY)) {}
27
28
    // Select LSE as clock source for the RTC
29
    MODIFY_REG(RCC->BDCR, RCC_BDCR_RTCSEL, RCC_BDCR_RTCSEL_LSE);
30
    
31
    // Enable the RTC
32
    SET_BIT(RCC->BDCR, RCC_BDCR_RTCEN);
33
34
    // Wait until RTC is synchronized
35
    while(!READ_BIT(RTC->CRL, RTC_CRL_RSF)) {}
36
37
    // Wait until last write operation is done
38
    while(!READ_BIT(RTC->CRL, RTC_CRL_RTOFF)) {}
39
40
    // Enable second interrupt
41
    SET_BIT(RTC->CRH,RTC_CRH_SECIE);
42
43
    // Wait until last write operation is done
44
    while(!READ_BIT(RTC->CRL, RTC_CRL_RTOFF)) {}
45
46
    // Enter configuration mode
47
    SET_BIT(RTC->CRL,RTC_CRL_CNF);
48
49
    // Divide oscillator frequency by 32767+1 to get seconds
50
    RTC->PRLL=32767;
51
    RTC->PRLH=0;
52
53
    // Leave configuration mode
54
    CLEAR_BIT(RTC->CRL,RTC_CRL_CNF);
55
56
    // Wait until last write operation is done
57
    while(!READ_BIT(RTC->CRL, RTC_CRL_RTOFF)) {}
58
59
    // Enable interrupt in NVIC
60
    NVIC_EnableIRQ(3);
61
    __enable_irq();
62
}
63
64
65
void initIo()
66
{
67
68
    // Enable Port A
69
    SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPAEN);
70
71
    // PA5 = Output
72
    MODIFY_REG(GPIOA->CRL, GPIO_CRL_CNF5 + GPIO_CRL_MODE5, GPIO_CRL_MODE5_0);
73
}
74
75
76
int main(void)
77
{
78
    initIo();
79
    initRtc();
80
81
    while(1){};
82
}

Für den RTC_Handler musste ich einen Eintrag in der Interrupt-Vektor 
Tabelle in startup_stm32.s vornehmen (da stand eine 0 drin):
1
  .word  PendSV_Handler
2
  .word  SysTick_Handler
3
  .word  0
4
  .word  0
5
  .word  0
6
  .word  RTC_Handler <----- Hier war eine 0
7
  .word  0
8
  .word  0

Habe ich das so richtig gemacht?

von Dr. Sommer (Gast)


Lesenswert?

Vielleicht solltest du in der ISR noch das SECF Flag im CRL Register 
abfragen, um sicher zu gehen, dass wirklich eine Sekunde vergangen ist. 
Und wenn du eigene Makros wie SET_BIT verwendest wäre es nett deren 
Definition mitzugeben...

von Dr. Sommer (Gast)


Lesenswert?

Oh sorry, ich seh gerade dass die Makros aus der stm32f1xx.h kommen ;-)

von Stefan F. (Gast)


Lesenswert?

Momentan ist der sekunden-interrupt die einzige aktivierte Quelle für 
die ISR. Sobald ich auch andere Interrupts aktiviere sollte ich 
natürlich abfragen, was denn die ursache war. Danke für den Tip.

> SET_BIT ... ich seh gerade dass die Makros aus der stm32f1xx.h kommen
Wie machst du das denn normalerweise?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.