Guten Abend zusammen,
ich habe hier ein STM32F411RE (Nucleo Board) und verzweifle grade an der
Einstellung der Timer.
Es soll einfach 2 mal pro Sekunde der TIM2_IRQ Handler aufgerufen
werden, der dann die LED toggelt.
Wahrscheinlich fehlt nur eine kleine Einstellung ...
Ich habe jetzt folgenden Code:
int
main (int argc, char* argv[])
{
UNUSED(argc);
UNUSED(argv);
trace_printf("System clock: %u Hz\n", SystemCoreClock);
// enable clock on GPIO A
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
// set as output
GPIOA->MODER |= GPIO_MODER_MODER5_0;
// set to low speed (2MHz)
GPIOA->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR5);
//GPIOA->AFR[0] |= (GPIO_AF1_TIM2 << (5*4));
GPIOA->BSRR |= GPIO_BSRR_BS_5;
/**
* initialize the timer
*/
// enable clock to timer 2
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
// set prescaler value
TIM2->PSC = 10000 -1; // clock = 100.000.000 Hz -> CK_PSK = 10.000 Hz
// count to 5000
TIM2->ARR = 5000 -1; // 10.000 Hz / 5000 = 2 Hz
TIM2->DIER |= TIM_DIER_UIE; // enable update interrupt
// enable counter
TIM2->CR1 |= TIM_CR1_CEN;
while (1);
}
void
TIM2_IRQHandler(void)
{
// clear interrupt flag
TIM2->SR &= ~(TIM_SR_UIF);
// toggle Pin
GPIOA->ODR ^= GPIO_ODR_ODR_5;
}
Kann mir jemand hierbei helfen?
Vielen Dank schonmal,
Simon
PS: Reference Manual habe ich gelesen, aber vermutlich irgendwas
übersehen ...
Du musst dem Interrupt Controller noch sagen, dass er auch den Interrupt
für Timer 2 benutzen soll. Einfach nur eine Funktion TIM2_IRQHandler
definieren reicht leider nicht.
Sämtliche NVIC_* Funktionen stammen aus dem core_cm4.h Header, der über
den entsprechenden stm32f*.h automatisch mit eingebunden wird.
Wenn du das noch in deine main() packst sollte es funktionieren.
Wunder dich allerdings nicht, wenn die LED anfangs nur ganz kurz
aufblitzt bevor sie anfängt zu blinken. Das Update Interrupt Flag wird
schon mit starten des Timers gesetzt (TIM2->CR1 = TIM_CR1_CEN). Ist ja
quasi auch ein Update. Jedenfalls feuert der Interrupt sofort los und
nicht erst nachdem ARR=4999 ist.
Ob das mit der von dir angepeilten Interruptfrequenz hinhaut hängt
allerdings davon ab ob du irgendwo noch die Konfiguration für die PLL
versteckt hast. Ansonsten läuft der F411RE mit 16Mhz HSI und aus den 2Hz
werden ca 0,3Hz.
Ich würde den NVIC vorher noch initialisieren, sonst funktioniert er
manchmal nicht richtig
1
// initialize interrupt controller
2
NVIC_SetPriorityGrouping(3);
Desweiteren solltest du deinen Prescaler nochmal nachrechnen. Ich glaube
nicht, dass dein APB1 mit 100MHz takt. Laut ClockConfigurationTool darf
er nur mit maximal 42MHz takten.
Die TIMs laufen nicht mit HCLK, sondern mit PCLK1 oder PCLK2.
Danke ihr beiden für die Antworten.
Ich nutze ein Template des "GNU ARM Eclipse Plugin", das kümmert sich um
die PLL (Das Template musste ich allerdings ein bisschen anpassen, damit
der Chip auch mit 100MHz taktet, und nicht "nur" mit 84MHz (wie z.B.
STM32F401), da es für den F411RE kein fertiges Template gibt). Das
heißt, der Chip ist schon initialisiert und taktet zum Start von main()
schon mit 100MHz.
Das mit dem NVIC hatte ich überhaupt nicht auf dem Schirm. Das werde ich
heute Abend direkt einbauen und berichten.
Nun habe ich aber (nach weiterlesen der Doku) noch ein paar Fragen:
1. Es sollte doch auch möglich sein, die LED direkt (ohne zutun der CPU)
vom Timer zu schalten, oder? (Ich denke hier an einen der PWM Modi +
Alternate Funktion des Output Ports)
2. Wo ist der Unterschied zwischen PWM Modus 1 und 2?
Viele Grüße und danke schonmal,
Simon
Oh, da war ich zu langsam..
@Uwe:
Das wird nach der GPIO Konfiguration und vor der Timer Konfiguration
gemacht. ( "RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;" sollte doch richtig
sein, oder? )
@lil-b:
Das mit dem NVIC werde ich dann auch mal noch einbauen.
ABP1 taktet laut hier
(http://www.st.com/content/ccc/resource/technical/document/datasheet/b3/a5/46/3b/b4/e5/4c/85/DM00115249.pdf/files/DM00115249.pdf/jcr:content/translations/en.DM00115249.pdf
- Seite 15) mit 50MHz. 42MHz sollten es beim F401 sein.
@all:
Danke für den Hinweiß mit dem Takt von ABP1!
Demnach müsste mit dem Code oben die LED immer eine Sekunde an und eine
Sekunde aus sein, nicht jeweils eine halbe Sekunde?
Kann ich aus versehen APB1 auf 100MHz getaktet haben und den Chip
beschädigen? Die PLL kann ich heute Abend hier auch noch posten, wenn
das relevant sein sollte?
So, und noch einmal ich:
Ich habe im Bild nun einmal meine aktuelle Konfiguration eingestellt.
Im Bild sieht man aber auch, dass sich dort der APB1 Timer Clock von dem
APB1 Periperial Clock unterscheidet.
Heißt das nun, dass die Timer, die APB1 nutzen (TIM2,3,4,5) mit 100MHz
getaktet sind, die restliche Peripherie wie USART, IC2, ... am APB1 aber
nur mit 50MHz?
Dann würde es ja stimmen, so wie es ist, oder?
Und dann noch eine Frage: macht es einen Unterschied (Takt "unsauberer"
oder so etwas), wie ich die PLL konfiguriere um von den 8MHz HSE auf
100MHz SYSCLK zu kommen, oder ist das egal?
Also als Beispiel:
PLL_M = 8
PLL_N = 400
PLL_P = 4
oder
PLL_M = 4
PLL_N = 100
PLL_P = 2
Grüße und nochmal allen, die sich meinen vielen Fragen stellen, vielen
Dank :-)
Simon
PLLM sollte auf 2MHz laufen.
> The software has to set these bits correctly to ensure that the VCO input> frequency ranges from 1 to 2 MHz. It is recommended to select a frequency> of 2 MHz to limit PLL jitter.
Ich habe für 100MHz:
1
PLLM 4 -> 2MHz (8MHz/4)
2
PLLN 200 -> 400MHz (2MHz * 200)
3
PLLP 4 -> 100MHz (400MHz/ 4) APB2
4
PLLQ 8 -> 50MHz (400MHz / 8) APB1
APB1 sollte für USB auf 48MHz laufen.
Edit hat es dann doch gefunden.
RM0383 Seite 91/836:
> The maximum allowed frequency of the low-speed APB1 domain is 50 MHz
Jetzt muss ich auch mal Fragen. Ich habe jetzt im Reference Manual nix
gefunden, vielleicht versteckt es sich hinter einem der Bilder?!?
Aber kann es sein, dass der TIM2 bis TIM5 mit Systemtakt läuft und nicht
mit APB1 (50MHz)? Also mit 100MHz, wenn denn so zurecht gebastelt?!?
Ich glaube, die Antwort habe ich eine halbe Seite unter der von dir
zitierten Stelle im Reference Manual (RM0383, S.91) gefunden:
>The timer clock frequencies for STM32F411xC/E are automatically set by hardware.>There are two cases:> 1. If the APB prescaler is 1, the timer clock frequencies are set to the same> frequency as that of the APB domain to which the timers are connected.> 2. Otherwise, they are set to twice (×2) the frequency of the APB domain> to which the timers are connected.
Demnach wäre es so, dass wenn der APB1 Prescaler auf /2 steht (was er ja
müsste, bei 100MHz HCLK und 50MHz APB1 Peripherial Clock), die Timer,
die an APB1 verbunden sind, mit 100MHz takten.
Wenn mir das nochmal jemand so bestätigen kann, wäre ich aber trotzdem
dankbar.
Simon Richter schrieb:> um von den 8MHz HSE auf> 100MHz SYSCLK
Hast du denn einen externen Quarz auf dein Nucleo gelötet? Die HSI läuft
über einen internen 16Mhz Oszillator (Ch. 6.2.2 RefMan).
Simon Richter schrieb:> Ich habe im Bild nun einmal meine aktuelle Konfiguration eingestellt.> Im Bild sieht man aber auch, dass sich dort der APB1 Timer Clock von dem> APB1 Periperial Clock unterscheidet.> Heißt das nun, dass die Timer, die APB1 nutzen (TIM2,3,4,5) mit 100MHz> getaktet sind, die restliche Peripherie wie USART, IC2, ... am APB1 aber> nur mit 50MHz?
Ich sehe zwar das Bild nicht, aber wenn der APB1 Prescaler auf
mindestens zwei gesetzt ist (was ja sein muss bei max.50Mhz), dann
laufen die Timer an APB1 mit der doppelten Frequenz von APB1. Es sollte
also so sein wie du beschrieben hast.
Simon Richter schrieb:> 1. Es sollte doch auch möglich sein, die LED direkt (ohne zutun der CPU)> vom Timer zu schalten, oder? (Ich denke hier an einen der PWM Modi +> Alternate Funktion des Output Ports)
Ja, das geht auch direkt und auch ohne Interrupts:
GPIO Setup:
// set capture compare mode to "pwm mode 1", i.e. output active if CNT<CCR
15
TIM2->CCMR1=TIM_CCMR1_OC1M_2|TIM_CCMR1_OC1M_1;
16
17
// enable the capture compare output
18
TIM2->CCER=TIM_CCER_CC1E;
19
20
// enable counter
21
TIM2->CR1|=TIM_CR1_CEN;
Also PWM mode 1 bedeutet "output active" wenn TIMx->CNT < TIMx->CCR und
bei PWM mode 2 ist es genau anders herum. D.h. du drehst die Polarität
für den gesamten Timer um.
Die Polaritäten kannst du aber auch für die einzelnen
Capture/Compare-Kanäle einstellen, hiermit verdrehst du z.B. für CC1 die
Polarität:
Christopher J. schrieb:> Hast du denn einen externen Quarz auf dein Nucleo gelötet? Die HSI läuft> über einen internen 16Mhz Oszillator (Ch. 6.2.2 RefMan).
Jupp, der NucleoF411RE hat nen Externen 8MHz.
Christopher J. schrieb:> GPIOA->MODER |= GPIO_MODER_MODER5_1;
Je nach Pin sollte man den vorher Resetten. Nicht jeder Pin ist am
Anfang auf 0. Darauf bin ich zwischendurch auch einmal reingefallen.
> Reset values:> • 0x0C00 0000 for port A> • 0x0000 0280 for port B> • 0x0000 0000 for other ports
Nico W. schrieb:> Christopher J. schrieb:>> GPIOA->MODER |= GPIO_MODER_MODER5_1;>> Je nach Pin sollte man den vorher Resetten. Nicht jeder Pin ist am> Anfang auf 0. Darauf bin ich zwischendurch auch einmal reingefallen.
Ja das stimmt, da muss man aufpassen. Für den PA5 sollte es aber so
passen.
Nico W. schrieb:> Christopher J. schrieb:>> Hast du denn einen externen Quarz auf dein Nucleo gelötet? Die HSI läuft>> über einen internen 16Mhz Oszillator (Ch. 6.2.2 RefMan).>> Jupp, der NucleoF411RE hat nen Externen 8MHz.
Die Frage war eigentlich an Simon gerichtet :D Musste grade selber mal
nachschauen ob neuere Revisionen den X3 standardmäßig bestückt haben,
weil bei meinem ist es (leider) nicht so.
Aber um auf deine Frage zurück zu kommen:
Nico W. schrieb:> Aber kann es sein, dass der TIM2 bis TIM5 mit Systemtakt läuft und nicht> mit APB1 (50MHz)? Also mit 100MHz, wenn denn so zurecht gebastelt?!?
Ja, die Timer an APB1 (TIM2 bis TIM5) laufen standardmäßig mit doppeltem
APB1 Takt, wenn der Prescaler für APB1 >= 2 ist. Wenn der Prescaler
gleich zwei ist entspricht das dem Systemtakt. Es gibt noch die
Möglichkeit die Timer mit vierfachem Takt laufen zu lassen, wenn der
Prescaler von APB1 >= 4 ist. Das ist auf Seite S.132 alles relativ kurz
und knapp beschrieben.
Das gleiche gilt auch für APB2, wobei man den ja auch direkt mit
Systemtakt, also 100 Mhz laufen lassen kann, also den Prescaler auf 1
belassen kann.
Übrigens ist Q soweit ich weiß für USB und SDIO zuständig und darf dafür
maximal 48 Mhz sein bzw. muss exakt 48 Mhz sein.
Nico W. schrieb:> PLLQ 8 -> 50MHz (400MHz / 8) APB1
Wenn man PLLN auf 192 reduziert passt aber alles, wobei der Prozzi dann
eben "nur" mit 96 Mhz rennt und APB1 eben auch 48 Mhz hat.
Christopher J. schrieb:> Das ist auf Seite S.132 alles relativ kurz> und knapp beschrieben.
Danke, guck ich mir nochmal genauer an.
Christopher J. schrieb:> Nico W. schrieb:>> PLLQ 8 -> 50MHz (400MHz / 8) APB1>> Wenn man PLLN auf 192 reduziert passt aber alles, wobei der Prozzi dann> eben "nur" mit 96 Mhz rennt und APB1 eben auch 48 Mhz hat.
Wenn man etwas mutig ist, kann man den STM auch auf 108MHz laufen
lassen. Läuft bei meinem sehr stabil.
1
PLLM 2 -> 2MHz
2
PLLN 216 -> 432MHz
3
PLLP 4 -> 108MHz
4
PLLQ 9 -> 48MHz
Wobei dann TIM2 wohl immer noch auf 'nur' 96MHz läuft, der Prozessor
aber auf 108MHz.
Nico W. schrieb:> PLLM 2 -> 2MHz> PLLN 216 -> 432MHz> PLLP 4 -> 108MHz> PLLQ 9 -> 48MHz> Wobei dann TIM2 wohl immer noch auf 'nur' 96MHz läuft, der Prozessor> aber auf 108MHz.
Ich glaube du verwechselst da was. Die beiden APBs werden aus dem Takt
des AHB versorgt und dieser wiederum aus der SYSCLK, was in deinem Fall
die PLLCLK ist.
Das einzige was über den Teiler PLLQ versorgt wird sind USB und SDIO.
Bei deiner Konfiguration sollte also TIM2 mit 108Mhz laufen und der APB1
mit 54Mhz. Das kann funktionieren, ist aber definitiv außerhalb der
Specs.
Hab dir mal einen Screenshot aus der Konfiguration in CubeMX angehängt
(finde ich für PLL Konfiguration sehr übersichtlich, auch wenn ich den
sonstigen HAL-Kram nicht mag). Das gleiche bekommst du aber auch wenn du
einen Blick auf "clock tree" auf S.90 wirfst.
Ich habe ein 08/15 Nucleo F411RE.
X3 habe ich noch nicht im Einsatz. Muss mal mein Board eh genauer
ansehen, was da drauf ist. Auf manchen soll ja sogar ein 32k drauf sein.
So, guten Morgen.
Gestern kamen mir leider ein paar Dinge dazwischen, deswegen melde ich
mich jetzt erst wieder.
Das mit dem NVIC hat das anfängliche Problem gelöst. Auch das mit den
verschiedenen PWM Modi ist nun klar - danke dafür.
Die Konfiguration der PLL habe ich jetzt noch nicht geändert, werde ich
aber noch tun, um dem hier:
> The software has to set these bits correctly to ensure that the VCO input> frequency ranges from 1 to 2 MHz. It is recommended to select a frequency> of 2 MHz to limit PLL jitter.
gerecht zu werden.
@Christopher:
In deinem Beispiel zum PWM fehlt noch das beschreiben von TIM2->CCR1 um
den duty cycle zu bestimmen :-)
@all
Vielen Dank für die ausführlichen Erklärungen, auch wenn ihr mich
anfangs etwas geschockt habt mit dem Takt von den Timern :-P
Simon R. schrieb:> @Christopher:> In deinem Beispiel zum PWM fehlt noch das beschreiben von TIM2->CCR1 um> den duty cycle zu bestimmen :-)
Oh stimmt, ist wohl irgendwo zwischen Strg-C und Strg-V verloren
gegangen ;)
Ohne Wert im CCRx tut sich natürlich genau gar nichts.
Nico W. schrieb:> X3 habe ich noch nicht im Einsatz. Muss mal mein Board eh genauer> ansehen, was da drauf ist. Auf manchen soll ja sogar ein 32k drauf sein.
Ich hab auch echt bis gestern geglaubt man müsste den X3 separat
bestücken um das Ding mit HSE betreiben zu können. Es gab hier auch
irgendwo mal einen Artikel dazu wie man das genau anstellt und den habe
ich dann leider nicht mehr gefunden. Naja, im User Manual zu den
Nucleo64 steht es jedenfalls drin und da war dann auch der Hinweis auf
den Quarz vom ST-Link. Oh man...
Bei mir ist jedenfalls auch so ein 32k Quarz verlötet. Laut dem Manual
ist das bei Boards ab Revision C-02 der Fall.
Christopher J. schrieb:> Bei mir ist jedenfalls auch so ein 32k Quarz verlötet. Laut dem Manual> ist das bei Boards ab Revision C-02 der Fall.
Jetzt ist nur die Frage ab wann C-02 kam. Ich habe mein Board jetzt ca.
ein Jahr.
Christopher J. schrieb:> Ich hab auch echt bis gestern geglaubt man müsste den X3 separat> bestücken um das Ding mit HSE betreiben zu können.
Ich hatte bisher keine Ahnung, dass da X3 für nen Quarz vorgesehen ist
:)
Ich bin aber auch ganz naiv in den STM reingestolpert und hatte mich
damals durch das GCC4MBED durchgequält und den kompletten Ballast von
Bord geschmissen, bis mein µC lief.
Ich habe das Nucleo auch in etwa seit einem Jahr. Die Revision steht
aber auch auf einem kleinen weißen Aufkleber drauf. Den X2 kann man aber
auch leicht erkennen. Ist ein schwarzes SMD-Teil links unten im Eck
(wenn der ST-Link oben ist).
Gestern mal geguckt. Ich hab nen C-03. Also mit Quarz. Jetzt muss ich
mir nur noch überlegen wie warum und wieso er gut in ein Projekt von mir
passen könnte. :)