Hallo liebes Forum,
zur Zeit versuche ich eine ms-Delay-Funktion auf einem F103RB mit 72 MHz
ohne externen Takt zu implementieren.
Mein bisheriger Lösungsansatz:
TIM2 habe ich wie folgt konfiguiert:
Systemclock = 72000000 Takte
1 ms = 1000 Hz also 72000 - 1 Takte
timer.c
Schicke ich per USART ein 0x30 so bekomme ich als Antwort 0xAA und die
LED blinkt kurz auf. Normalerweise erwarte ich ein 1 sekündiges
Aufblinken.
Habt Ihr eine Idee?
Danke und Gruß
Daniel
Bevor man deine "von hinten durch die Brust ins Auge" - Lösung
näher beleuchtet, die Frage:
Soll das eine Übung sein den Timer zu verstehen oder weisst
du es nicht besser wie man das einfacher Lösen kann?
Basic Programmierer schrieb:> Soll das eine Übung sein den Timer zu verstehen oder weisst> du es nicht besser wie man das einfacher Lösen kann?
Ja genau. Ein Delay auf Basis des Systicks bekomme ich hin nu wollte ich
mir die Timer mal genauer anschauen
Stefanus F. schrieb:>> Normalerweise erwarte ich ein 1 sekündiges Aufblinken.>> Dann lass doch den ganzen Kram rund um den seriellen Port erstmal raus.
Blinkt dann schnell und keine Sekunde.
Kontrolliere mal, ob SystemCoreClock den erwarteten Wert (72Mhz)
enthält.
> Blinkt dann schnell
Kannst du die Frequenz messen? Daraus könnte ein Hinweis auf die
Fehlerursache entstehen.
Stefanus F. schrieb:> Kontrolliere mal, ob SystemCoreClock den erwarteten Wert (72Mhz)> enthält.>>> Blinkt dann schnell>> Kannst du die Frequenz messen? Daraus könnte ein Hinweis auf die> Fehlerursache entstehen.
Das ist mein nächster Schritt.
Daniel V. schrieb:> while((TIM2->CNT - StartTick) <= msTick)
Im upcounter mode hast du hier gleich ein Überlauf. Man muss den
Subtrahend tauschen.
Aber warte mal. Du bräuchtest so einen 32 bit timer.
> ConfigTIM2.TIM_Prescaler = (SystemCoreClock/DELAY_TIM_FREQUENCY_MS)> -1;
Das geht so nicht.
Man könnte auf 50Hz auflösen, also ein CNT entspricht 20ms und das 20
fache einer ms. Besser wäre es mit einer Hilfsvariable und 1ms Timer.
Moin,
der Prescaler ist doch nur 16bit breit. Wenn man von 72MHz auf 1kHz
kommen will braucht es einen Teiler von 72000, der in 16 bit nicht
reinpasst. Man könnte den APB1 Presaceler auf /4 setzen und haette
dann fuer TIM 36MHz Takt. Dann muesste es mit 36000 als Prescaler in
TIM2 klappen.
Aber wieso laesst du ihn nich frei laufen?
Ich musste bei meinem Freilaufen Timestamp Timer noch ein Update event
generieren damit der Prescaler Wert auch uebernommen wird. Was sonst
erst beim erst Ueberlauf passiert waere.
Stefanus F. schrieb:> Kontrolliere mal, ob SystemCoreClock den erwarteten Wert (72Mhz)> enthält.>>> Blinkt dann schnell>> Kannst du die Frequenz messen? Daraus könnte ein Hinweis auf die> Fehlerursache entstehen.
Der 103 kann doch nur max. 72 MHz. Und wenn der Blinker zu schnell ist
und es am coreclock liegen soll, müßte der ja deutlich schneller als 72
MHz sein.
Darth Moan schrieb:> Wenn man von 72MHz auf 1kHz> kommen will braucht es einen Teiler von 72000, der in 16 bit nicht> reinpasst. Man könnte den APB1 Presaceler auf /4 setzen und haette> dann fuer TIM 36MHz Takt. Dann muesste es mit 36000 als Prescaler in> TIM2 klappen.
Nicht eher /2 statt /4?
Darth Moan schrieb:> der Prescaler ist doch nur 16bit breit. Wenn man von 72MHz auf 1kHz> kommen will braucht es einen Teiler von 72000, der in 16 bit nicht> reinpasst. Man könnte den APB1 Presaceler auf /4 setzen und haette> dann fuer TIM 36MHz Takt. Dann muesste es mit 36000 als Prescaler in> TIM2 klappen.
Danke. Das war es. Hier der vorläufige Lösungscode:
1
RCC->APB1ENR|=RCC_APB1ENR_TIM2EN;
2
RCC->CR|=RCC_CR_CSSON|RCC_CR_PLLON;
3
RCC->CFGR|=RCC_CFGR_PPRE1_DIV4;
4
5
TIM_TimeBaseInitTypeDefConfigTIM2;
6
TIM_TimeBaseStructInit(&ConfigTIM2);
7
ConfigTIM2.TIM_Prescaler=36000;
8
ConfigTIM2.TIM_Period=UINT16_MAX;
9
ConfigTIM2.TIM_ClockDivision=0;
10
ConfigTIM2.TIM_CounterMode=TIM_CounterMode_Up;
11
TIM_TimeBaseInit(TIM2,&ConfigTIM2)
Aber wieso laesst du ihn nich frei laufen?
Ich musste bei meinem Freilaufen Timestamp Timer noch ein Update event
generieren damit der Prescaler Wert auch uebernommen wird. Was sonst
erst beim erst Ueberlauf passiert waere.
Kannst Du mir ein Beispielcode zeigen?
Danke euch und Gruß
Daniel V. schrieb:> einem F103RB mit 72 MHz ohne externen Takt zu implementieren
Kann der F103 überhaupt 72Mhz ohne externen Takt?! ? Geht der HSI nicht
/2 in den PLL und kann somit ohne HSE maximal 64Mhz?
Rene K. schrieb:> ann der F103 überhaupt 72Mhz ohne externen Takt?! ? Geht der HSI nicht> /2 in den PLL und kann somit ohne HSE maximal 64Mhz?
Du hast vollkommen recht. Ich habe mir den Clocktree im CubeMX
angeschaut.
Die Serielle macht nu auch nicht mehr was sie soll. Guter Hinweis.
Danke.
Daniel V. schrieb:> Kannst Du mir ein Beispielcode zeigen?>> Danke euch und Gruß
1
__TIM5_CLK_ENABLE();
2
/* TIM5 counts up in steps of 10us to provide a 32bit time stamp value */
3
TIM5->PSC=1079;
4
TIM5->CR1=TIM_CR1_CEN;
5
TIM5->EGR=TIM_EGR_UG;
Das ist mein Freiläufer (auf dem F746). Der APB1 Timer clock ist 108MHz.
Ich weiss, ist nicht ganz sauber, da ich mich auf die Reset-Werte
verlasse. Wollte ich auch schon längst geändert haben. Aber nichts
länger sich länger und harnäckiger als ein Provisorium.
Ich benutze den fuer Timestamps. Ich brauche Timestamps im 10µs Raster,
32Bit breit. Da hab ich TIM5 hergenommen. Und durch die Differenzbildung
kann man auch ein Delay mit einem freilaufenden Timer machen.
Ich nehme dafuer aber DWT->CYCCNT im Macro:
Da das Delay (bei mir) nur mit Konstanten aufgerufen wird, wird die
Multipliketion schon beim Build aufgeloest.
BTW.
Daniel V. schrieb:> volatile uint32_t StartTick = TIM2->CNT;
Das volatile fuer die lokale Variable ist nicht notwendig/förderlich.
Beim GCC (-O3) sorgt es dafür, dass StartTick auf dem Stack landet
statt im Register. Er liest StartTick fuer jeden Vergleich neu ausm
Speicher. Ist bei einer Warteschleife jetzt nicht gerade tragisch,
aber unnötig.
Vielen Dank. Interessanter Gedanke.
Mal noch eine allegmeine Frage. Wie berechne ich den Timer? Im diesen
Falle habe ich:
SystemCoreClock = (720000 / 2000) = 36000.
Dieses wieder durch 65535 = 0,54 ms
Der Bezeichner msTick in void delay_ms(uint32_t msTick) wird mit 2
multipliziert d.h. es ergibt sich 1,08 ms.
timer.c
Mit einem Oszi habe ich aber genau 1 ms gemessen bzw für delay_ms(1000)
1 Sekunde und für delay_ms(500) 500 ms usw. Der Code funktioniert also,
aber warum tut er das? Wie kann das sein? Habe ich hier ein
Verständnisproblem?
Danke und Gruß
Moin,
Daniel V. schrieb:> Mal noch eine allegmeine Frage. Wie berechne ich den Timer? Im diesen> Falle habe ich:>> SystemCoreClock = (720000 / 2000) = 36000.> Dieses wieder durch 65535 = 0,54 ms
Äh, hast du nicht gesagt 72MHz also 72000000?
Du benutzt SPL/HAL, ich weniger. Daher bin ich mit den Einstellungen
dort nicht ganz sicher. Aber ich glaube,
Daniel V. schrieb:> ConfigTIM2.TIM_Period = UINT16_MAX;
bestimmt den Überlaufpunkt (TIMx_ARR). Der Counter zählt dann von
0..ARR. Und wieder von 0..ARR usw. Aber dieses Überlaufevent nutzt
du ja gar nicht.
Mit Prescaler auf 36000 zählt TIM2 im 500µs Takt, also alle 500µs
ein Inkrement (TIM_CounterMode_Up). Du holst dir ja den aktuellen
Counter und nutzt ihn. Der Überlauf sollte erst nach 65536*0,5ms
erfolgen, also nach 32,7xx Sekunden. Wenn ich das richtig interpretiere!
Es sollte dann also nicht möglich sein, eine Wartezeit mit >33s zu
erreichen. Der TIM2 Counter wuerde den zugehörigen Wert nie erreichen.
Rene K. schrieb:> Daniel V. schrieb:>> einem F103RB mit 72 MHz ohne externen Takt zu implementieren>> Kann der F103 überhaupt 72Mhz ohne externen Takt?! ? Geht der HSI nicht> /2 in den PLL und kann somit ohne HSE maximal 64Mhz?Daniel V. schrieb:> Du hast vollkommen recht.
Das passt alles nicht so recht zusammen:
Darth Moan schrieb:> Äh, hast du nicht gesagt 72MHz also 72000000?
Bitte nochmal gegenchecken ob nun 72Mhz oder 64Mhz Core Takt!
Moin,
Rene K. schrieb:> Bitte nochmal gegenchecken ob nun 72Mhz oder 64Mhz Core Takt!
Hab ich in ein falsches RefMan geschaut?
Aus RM0008
STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and
STM32F107xx advanced Arm®-based 32-bit MCUs
Figure 11. Clock tree:
"1. When the HSI is used as a PLL clock input, the maximum system
clock frequency that can be achieved is 36 MHz."
RCC_CFGR:
" PLLMUL[3:0]: PLL multiplication factor
These bits are written by software to define the PLL multiplication
factor. They can be written only when PLL is disabled.
000x: Reserved
0010: PLL input clock x 4
0011: PLL input clock x 5
0100: PLL input clock x 6
0101: PLL input clock x 7
0110: PLL input clock x 8
0111: PLL input clock x 9
10xx: Reserved
1100: Reserved
1101: PLL input clock x 6.5
111x: Reserved"
Ein Multiplikator von 16 ist da nicht gelistet.
Wenn AHB /1 und APB1 /1 wird TIM2 mit APB1 *2 getaktet, also 72MHz.
Allerdings muesste dann ja der Core nur 36MHz kriegen.
Oder?
Darth Moan schrieb:> Ein Multiplikator von 16 ist da nicht gelistet.> Wenn AHB /1 und APB1 /1 wird TIM2 mit APB1 *2 getaktet, also 72MHz.> Allerdings muesste dann ja der Core nur 36MHz kriegen.> Oder?
Ja, ich bin auch total verwirrt. Die Peripherie bekommt 36 MHz, die
Timer hingegen haben noch einen Faktor 2, also 72 MHz. Der Sysclock ist
ebenfalls 72 MHz.
Siehe Bild
GPIOA -> APB1
USART2 und TIM2 -> APB2
Ich habe 72 MHz, weil ich ja den Systemclock durch 2000 dividiere
(36000). Dort bekomme ich 0,5 µs. Diesen Wert mit Linksshift
multipiziert und somit habe ich 1 ms. Gebe ich 64 MHz also als
Prescalerwert 32000 direkt ein, passt die Geschichte nicht mehr.
Darth Moan schrieb:> Hab ich in ein falsches RefMan geschaut?
Nein, damit arbeite ich auch, deshalb bin ich verwirrt, da CubeMX das
genauso anzeigt, wie du es gesagt hast.
Ich benutze das Tool nur, um meine Clockwerte einzustellen, nicht die
HAL selber, sondern die SPL.
Moin,
oha, ich bin in die falsche Device Class "gerutscht". Sollte eigentlich
nicht passieren. :-(
Aber trotzdem duerfte ein 72MHz TIM2 Clock nur bei 36MHz AHB Clock
moeglich sein.
Wie ist denn deine Clock Init?
Passt dein Systick timer zu 64MHz?
Darth Moan schrieb:> Wie ist denn deine Clock Init?> Passt dein Systick timer zu 64MHz?
Nein, der Prozessortakt ist 72 MHz. Soeben gemessen.
Gruß
Daniel
Moin,
Daniel V. schrieb:> Nein, der Prozessortakt ist 72 MHz. Soeben gemessen.
Das duerfte aber laut RefMan mit HSI als Clock Source nicht moeglich
sein.
Dazu muessten 8MHz in die PLL gehen mit Faktor 9 gibt das 72MHz.
Der 8MHz HSI witrd erst /2 also 4MHz in die PLL geführt, was max 64MHz
ergibt (*16).
Bist du sicher, das du nicht mit externen 8MHz HSE in die PLL gehst?
Dann waere das problemlos moeglich: PLL *9; AHB /1; APB1 /2; TIM2 APB1
*2.
Nur dann sollten Core und TIM2 72MHz bekommen koennen.
Es gehen noch andere Kombinationen ZB: 6Mhz *12.
Ich weiss ja nicht, was auf deinem Board drauf ist.
> Nur dann sollten Core und TIM2 72MHz bekommen koennen.> Es gehen noch andere Kombinationen ZB: 6Mhz *12.> Ich weiss ja nicht, was auf deinem Board drauf ist.
Es ist zur Zeit ein Nucleoboard.
Nein, per Default beziehen alle STM32F1 Mikrocontroller ihren Takt vom
internen R/C Oszillator.
Wenn du eine externe Taktquelle verwenden willst, musst du das
programmieren.
Moin,
mit Default meine ich:
The board marking MB1136 C-02 (or higher) corresponds to a board,
configured to use ST-LINK MCO as clock input.
MCO from ST-LINK:
MCO output of ST-LINK MCU is used as input clock. This frequency cannot
be changed, it is fixed at 8 MHz and connected to PF0/PD0/PH0-OSC_IN of
the STM32 microcontroller.
Andernfalls muss man Lötbrücken umsetzten, wenn kein 8MHz Signal auf
den HSE Input gelegt werden soll. Will man den Pin für etwas anderes
nutzen muss man SB 50 oder 16 oeffnen, sonst liegt dort ein 8MHz
clock an.
Ob man diese Clock als Source fuer die PLL nehmen möchte oder nicht,
kann man per SW wählen, nicht aber die Lötbrücken, die sind HW.