Halbe SYSCLK Geschwindigkeit beim STM32F205 PLL

OP #4533604
Lesenswert?
• ▲
▼
Moin zusammen, lange hier nichts mehr gepostet. Und jetzt wo ich dran 
brin... kommt erstmal ne Frage.

Ich habe ein selbstentwickeltes STM32F205 Board, der Hardwaremäßig 
funktioniert. Flashen, programmieren, LEDs blinken, alles toll.

I möchte jetzt die Frequenz des SYSCLK auf ~98 MHz erhöhen (12.288 MHz 
Kristall x 8), leider bekomme ich beim Ausgang des PLLs nur die Hälfte? 
Um das zu testen, habe ich ein SysTick timer konfiguriert, der jede 1000 
Ticks ein Interrupt auslöst. Da wird kurz mal ein LED hoch und runter 
geschaltet.

Gemessen am Oszi funktioniert der SysTick ganz gut bei HSI oder HSE (je 
16 oder 12.288 KHz Signal), aber wie gesagt, beim PLL, zeigt es dann nur 
49 KHz statt erwarteten 98 KHz.

Weiter runter habe ich das Code mit Kommentare. Und Entschuldigung wenn 
mein Deutsch etwas komisch klingt, wohne seit ein paar Jahren nicht mehr 
in DE!

Albert
1
#include "typedef.h"
2

3
#include "stm32f2xx.h"
4
#include "stm32f2xx_it.h"
5

6
#include "digIo.h"
7

8
void initFlash(void);
9
void initClocks(void);
10

11
char ledsOn = 0x1;
12

13
int main(void){
14

15
    initFlash();
16
    initClocks();
17

18
    /** Set timer to 98 KHz **/
19
  if (SysTick_Config(1000))
20
  {
21
    /* Capture error */
22
    while (1);
23
  }
24

25
    initLEDS();
26

27
    setLED_Off(0);
28
    setLED_Off(1);
29
    setLED_Off(2);
30
    setLED_Off(3);
31

32
    setLED_On(0);
33
    setLED_On(1);
34
    setLED_On(2);
35
    setLED_On(3);
36

37
    while(1){
38

39
        if(timerExpired == 1){
40
            timerExpired = 0;
41

42
            setLED_On(3);
43
            setLED_Off(3);
44
        }
45
    }
46

47
}
48

49
void initFlash(void){
50

51
  /** Set three wait states **/
52
  FLASH->ACR |= FLASH_ACR_LATENCY_3WS ;
53
}
54

55
void initClocks(void){
56

57
  /** Initialize clock to external clock (12.288 MHz) **/
58
  RCC->CR |= RCC_CR_HSEON;
59
  while(!(RCC->CR & RCC_CR_HSERDY)){
60
    ;
61
  }
62

63
  /** Set PLL source to HSE **/
64
  RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE;
65

66
  /** Set M divider to 0x8 (/8) **/
67
  RCC->PLLCFGR |= (RCC_PLLCFGR_PLLM_3);
68

69
  /** Set N multiplier to 0x80 (x128) **/
70
  RCC->PLLCFGR |= (RCC_PLLCFGR_PLLN_7);
71

72
  /** Set P divider to 0x0 (/2) **/
73
  RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLP);
74

75
  /** Enable PLL **/
76
  RCC->CR |= RCC_CR_PLLON;
77
  while(!(RCC->CR & RCC_CR_PLLRDY)){
78
    ;
79
  }
80

81
  /** Set SW to PLL **/
82
  RCC->CFGR |= RCC_CFGR_SW_PLL;
83
  while(!(RCC->CFGR & RCC_CFGR_SWS_PLL)){
84
    ;
85
  }
86
}
OP #4534708
Lesenswert?
• ▲
▼
Ich meine in dem Fall ist der SystemCoreClock nur der Wert des 
erwarteten PLL Ausgangs.

Bei SysTick_Config(1000) heisst es (so wie ich das verstehe), nach 1000 
ticks (clocks), löse Interrupt aus.

Man kann auch SysTick_Config(SystemCoreClock/1000) konfigurieren, dann 
kommt der Interrupt eben alle 1 ms. Deswegen wird der Wert 
SystemCoreClock neu geschrieben.

Ich werde nochmal weiterschauen, mir ist aufgefallen ich habe was an 
Flash wait states und prefetch vergessen.
OP #4534725
Lesenswert?
• ▲
▼
Lösung gefunden.

Es scheint als ob man das RCC->PLLCFGR register in einem Schritt 
beschreiben muss. So sieht es jetzt aus
1
void initClocks(void){
2

3
  /** Initialize clock to external clock (12.288 MHz) **/
4
  RCC->CR |= RCC_CR_HSEON;
5
  while(!(RCC->CR & RCC_CR_HSERDY)){
6
    ;
7
  }
8

9
  /** Flash configuration **/
10
    /** Flash prefetch and cache ON, Flash 3 wait state **/
11
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS;
12

13
  /** Set M divider to 0x8 (/8) **/
14
  /** Set N multiplier to 0x80 (x128) **/
15
  /** Set P divider to 0x0 (/2) **/
16
  /** Set PLL source to HSE **/
17
    RCC->PLLCFGR = (0x8 | ((uint32_t)0x80 << 6) | (((0x2 >> 1) -1) << 16)) | (RCC_PLLCFGR_PLLSRC_HSE);
18

19
  /** Enable PLL **/
20
  RCC->CR |= RCC_CR_PLLON;
21
  while(!(RCC->CR & RCC_CR_PLLRDY)){
22
    ;
23
  }
24

25
  /** Set SW to PLL **/
26
  RCC->CFGR |= RCC_CFGR_SW_PLL;
27
  while(!(RCC->CFGR & RCC_CFGR_SWS_PLL)){
28
    ;
29
  }
30
}

Un es läuft wie erwartet, schön 98 Khz Interrupts ausgelöst.

Albert.
Gast #4535259
Lesenswert?
• ▲
▼
Albert F. schrieb:
> Ich meine in dem Fall ist der SystemCoreClock nur der Wert des
> erwarteten PLL Ausgangs.
>
> Bei SysTick_Config(1000) heisst es (so wie ich das verstehe), nach 1000
> ticks (clocks), löse Interrupt aus.

Ah, richtig. Das habe ich elegant überlesen.

Danke noch für den Hinweis. Bei mir ist aktuell der PLLCFGR zwar in 
einem durch, aber man weiß ja nie, was man daran mal ändern will.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.