Forum: Mikrocontroller und Digitale Elektronik STM32 32MHz nicht einstellbar


von Erwin (Gast)


Lesenswert?

Hi,
ich habe ein Display an einem STM32L053R8 hängen. Es wird über SPI 
angesprochen. Anfangs war der STM auf 4MHz eingestellt mit einem SPI 
Prescaler von 2. Da aber 320x240Pixel mit je 16Bit seeeehr lange 
Übertragungszeiten bei 2MHz SPI Takt verursachen, wollte ich den Takt 
etwas hochdrehen. Der HSI taktet mit 16MHz und wird durch 4 geteilt. Das 
Einfachste war also den Teiler weg zu nehmen. Das hat nach Anpassung des 
voltage scale auf Range2 auch geklappt.
8MHz sind schon deutlich besser, aber ich würde gern rausholen was geht. 
Deshalb habe ich auch noch PLL aktiviert. PLL_N auf 8 und PLL_M auf 4 -> 
32MHz Systemtakt und 16MHz SPI Takt. So steht es auch als Grenze im 
Datenblatt.
Nur fällt der Takt mit der Einstellung auf 8MHz (SPI) ab (Voltage scale 
natürlich auf Range1).
Dann probierte ich den Systemprescaler von 4 wieder einzustellen und 
entsprechend PLL_N auf 32 zu stellen. Das führte dazu das ein SPI Takt 
von 2MHz generiert wurde.
Wenn ich PLL_N auf 16 runterstelle klappt alles wie es sollte und ich 
erhalte 8MHz SPI bzw. 12MHz bei PLL_N = 24. Ebenso ohne dem 
Systemprescaler und mit PLL_N = 4 bzw 6.

Warum kann ich den Systemtakt nicht auf 32MHz stellen obwohl es im 
Datenblatt so eingetragen ist?

Meine SystemInit():
1
 RCC->APB1ENR |= (RCC_APB1ENR_PWREN); /* set Power Enable Bit */
2
  
3
  /* The voltage scaling allows optimizing the power consumption when 
4
   * the device is clocked below the maximum system frequency.
5
   * Range1: Up to 32MHz -> VOS_0
6
   * Range2: Up to 16MHz -> VOS_1
7
   * Range3: Up to 4,2MHz -> VOS
8
   */
9
  MODIFY_REG(PWR->CR, PWR_CR_VOS, PWR_CR_VOS_0);
10
11
  /* Enable the Internal High Speed oscillator (HSI or HSIdiv4) */
12
  MODIFY_REG(RCC->CR, 
13
         RCC_CR_HSION, 
14
         RCC_CR_HSION);
15
  
16
  /* wait until HSI is ready */
17
  while((RCC->CR & RCC_CR_HSIRDY) != RCC_CR_HSIRDY)
18
  {
19
  }
20
   
21
  /* calibration of HSI */
22
  MODIFY_REG(RCC->ICSCR, RCC_ICSCR_HSITRIM, (uint32_t)0x10 << 8);
23
24
  /* enable PLL */
25
  MODIFY_REG(RCC->CFGR, RCC_CFGR_PLLSRC, RCC_CFGR_PLLSRC_HSI);
26
  MODIFY_REG(RCC->CFGR, RCC_CFGR_PLLMUL, RCC_CFGR_PLLMUL8);
27
  MODIFY_REG(RCC->CFGR, RCC_CFGR_PLLDIV, RCC_CFGR_PLLDIV4);
28
  MODIFY_REG(RCC->CR, RCC_CR_PLLON, RCC_CR_PLLON);
29
  
30
        /* wait until PLL is ready */
31
  while((RCC->CR & RCC_CR_PLLRDY) != RCC_CR_PLLRDY)
32
  {
33
  }
34
35
  
36
  /* no further clock devision of SYSCLK */
37
  MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_CFGR_HPRE_DIV1);      
38
39
  /* select PLL as System Clock Source */
40
  MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL); 
41
  
42
43
  /* PCLK1 Configuration - Low-Speed APB1 HCLK not divided */ 
44
  MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_CFGR_PPRE1_DIV1);
45
46
  /* PCLK2 Configuration - High-Speed ABP2 HCLK not divided */
47
  MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, RCC_CFGR_PPRE2_DIV1); 
48
49
  /* Get system clock */
50
  SystemCoreClockUpdate();
51
  
52
  /*
53
   * start of LSE
54
   */
55
  RCC->APB1ENR |= (RCC_APB1ENR_PWREN | RCC_APB1ENR_CRSEN);
56
  
57
  /* Enable Write for LSE Activation */
58
  PWR->CR |= PWR_CR_DBP;
59
60
  /* Enable LSE */
61
  RCC->CSR |= RCC_CSR_LSEON;
62
  
63
  /* set Drive to 2 */
64
  RCC->CSR |= RCC_CSR_LSEDRV;
65
  
66
  /* Disable Write for LSE Configuration */
67
  PWR->CR &= ~PWR_CR_DBP;

: Gesperrt durch Moderator
von eagle user (Gast)


Lesenswert?

Mit PLLMUL x8 und HSI /1 müsste der VCO mit 128MHz laufen. Offiziell 
kann er aber "nur" 96MHz. Warum stellst du den PLLDIV so hoch ein? Das 
kostet doch unnötig Strom, nimm halt etwas in der Mitte.

von Andreas S. (igel1)


Lesenswert?

Schließe mich eagle user an und schlage vor:
1
/* enable PLL */
2
  MODIFY_REG(RCC->CFGR, RCC_CFGR_PLLSRC, RCC_CFGR_PLLSRC_HSI);
3
  MODIFY_REG(RCC->CFGR, RCC_CFGR_PLLMUL, RCC_CFGR_PLLMUL4);
4
  MODIFY_REG(RCC->CFGR, RCC_CFGR_PLLDIV, RCC_CFGR_PLLDIV2);
5
  MODIFY_REG(RCC->CR, RCC_CR_PLLON, RCC_CR_PLLON);

Viele Grüße

Igel1

: Bearbeitet durch User
von (º°)·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.· (Gast)


Lesenswert?

Das doch nur ein Zweizeiler (bei IAR):

FLASH_ACR_bit.LATENCY = 1; RCC_CFGR = 0x414D0000; RCC_CR = 0x1050300;
while(! RCC_CR_bit.PLLRDY); RCC_CFGR_bit.SW = 3;

Dazu muesste Mann nur das DB/Referenzmanual nicht nur lesen
sondern auch verstehen.

> Warum kann ich den Systemtakt nicht auf 32MHz stellen obwohl es im
> Datenblatt so eingetragen ist?

Die Antuinogeneration ist wohl unfaehig.

von Mehmet K. (mkmk)


Lesenswert?

> RCC_CFGR = 0x414D0000; RCC_CR = 0x1050300;

Sehr aussagekraeftige Befehle.

von eagle user (Gast)


Lesenswert?

Mehmet K. schrieb:

>> RCC_CFGR = 0x414D0000; RCC_CR = 0x1050300;
>
> Sehr aussagekraeftige Befehle.

Naja, beinahe. Die Konstanten sollten natürlich dezimal sein ;)

von Erwin (Gast)


Lesenswert?

Vielen Dank eagle und Andreas.
Die 96MHz für VCO habe ich total übersehen.
Jetzt läuft mein 16MHz SPI und der Bildaufbau geht gleich viel schneller 
;)

von Andreas S. (igel1)


Lesenswert?

> Vielen Dank eagle und Andreas.

Freut mich, wenn's funktioniert!

Viele Grüße
Igel1

von (º°)·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.· (Gast)


Lesenswert?

> Es könnte doch so einfach sein: Benötigte
> Taktfrequenz in ein Register schreiben und gut ist!

Rat mal was die beiden Zuweisungen machen :-)

>> RCC_CFGR = 0x414D0000; RCC_CR = 0x1050300;

Wenn statt dessen eine ganze A4-Seite voll eine ganze Litanei
angestimmt wird, ist wohl kaum der Kaefer schuld.

Immerhin: Das PLL-Register eines 56002 ist da intuitiver.

von avr (Gast)


Lesenswert?

P.L. schrieb im Beitrag #4913053:
> EINE Angabe pro Peripherie und für die MCU-Programmabarbeitung- mehr
> brauchts aus Anwendersicht nicht.

Es geht bei µCs nicht um Anwender. In der Industrie geht es um 
Stückzahlen. Die Programmierung muss nicht anwenderfreundlich sein, wenn 
das fertige Produkt 100k mal verkauft wird. Wenn es einfach sein soll, 
dann nimmt man halt eine SPS oder ähnliches. Dafür kostet die auch mehr.

Abgesehen davon stellst du dir das ein bisschen einfach vor. Sagen wir 
mal es gäbe ein Register für die Taktfrequenz des Controllers. Was macht 
der Controller wenn du was einstellst, was er nicht generieren kann? 
Einfach weil es keine passende Kombination aus Teiler und Multiplikator 
gibt? Im Endeffekt läuft es doch wieder darauf hinaus, dass ich 
nachschauen muss, ob meine Wunschfrequenz überhaupt möglich ist.

von Nop (Gast)


Lesenswert?

avr schrieb:

> der Controller wenn du was einstellst, was er nicht generieren kann?
> Einfach weil es keine passende Kombination aus Teiler und Multiplikator
> gibt? Im Endeffekt läuft es doch wieder darauf hinaus, dass ich
> nachschauen muss, ob meine Wunschfrequenz überhaupt möglich ist.

Wenn man nicht auf HSI laufen soll (30s Toleranz pro Stunde!), sondern 
man den HSE mit Quartz nutzen will, was dann? Der kann jede Frequenz 
haben. Soll der µC das etwa messen? Mit dem ungenauen HSI als Referenz?

von P.L. (Gast)


Lesenswert?

avr schrieb:
> Was macht
> der Controller wenn du was einstellst, was er nicht generieren kann?
> Einfach weil es keine passende Kombination aus Teiler und Multiplikator
> gibt?

Du bist ein Kind der heutigen Technik :-)
Einstellbar kann/soll natürlich nur etwas sein, was die Hardware dann 
auch ermöglicht. Intelligente Hardware verbirgt ihren inneren Aufbau 
samt aller Abhängigkeiten vor dem Anwender. Sie ermöglicht maximale 
Unabhängigkeit aller Peripheriemodule voneinander. Daneben ermöglicht 
das Clockmanagement wesentlich mehr Auswahl und Auflösung und kommt 
inkl. eines hochgenauen Zeitgebers als Basis-> dahin sollte sich die 
Entwicklung mal bewegen statt immer nur auf "dumme" Leistung und ein 
Universum an Konfigurationsmöglichkeiten zu setzen, die ja doch nur von 
der hölzernen Begrenztheit heutiger Hardware künden und den 
Softwareaufwand samt Fehlerpotential aufblasen. Threadthemen wie dieses 
hier könnten endlich Vergangenheit sein!

Nop schrieb:
> man den HSE mit Quartz nutzen will, was dann? Der kann jede Frequenz
> haben. Soll der µC das etwa messen? Mit dem ungenauen HSI als Referenz?

Was man von außen anschließt muß man dem intelligenteren Controller im 
Programm schlicht nur bekannt machen.

von P.L. (Gast)


Lesenswert?

P.S

avr schrieb:
> Die Programmierung muss nicht anwenderfreundlich sein

Mit dieser Einstellung wird das nie was!

von avr (Gast)


Lesenswert?

P.L. schrieb:
> avr schrieb:
>> Die Programmierung muss nicht anwenderfreundlich sein
>
> Mit dieser Einstellung wird das nie was!

Doch und zwar wenn es um Stückzahlen geht. Bei µCs ist der Preis ein 
starker Faktor. Wenn du damit nicht zurecht kommst, warum programmierst 
du dann µCs? Es gibt fertige Embedded-Linux-Module, auf denen so 
ziemlich alles abstrahiert ist. Dafür zahlt man eben mehr. Ich verstehe 
wirklich nicht, wo dein Problem ist.

Es macht auch gar keinen Sinn, für so eine Funktionalität Silizium zu 
verschwenden. Wenn man es bequem haben möchte, dann programmiert man 
einmal eine entsprechende Funktion. Der Compiler wertet diese zur 
Compilezeit aus und beschreibt die wenigen Register entsprechend.

von P.L. (Gast)


Lesenswert?

avr schrieb:
> P.L. schrieb:
>> avr schrieb:
>>> Die Programmierung muss nicht anwenderfreundlich sein
>>
>> Mit dieser Einstellung wird das nie was!
>
> Doch und zwar wenn es um Stückzahlen geht.

Auch dann nicht.
Die Gegenrechnung zu den Chip-Preisen in Gestalt vergeudeter 
Programmier/Fehlersuche/Recherchestunden möchte ich in Summe gern mal 
sehen!

Aber man kann/muss sich natürlich mangels Alternative (wunschlos) mit 
dem Vorhandenen zufriedengeben. So ein Forum soll ja auch nicht 
überflüssig werden :)

Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.