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.
1 | // set priority for TIM2 interrupt
|
2 | NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 6, 0)); |
3 | |
4 | // enable interrupt for timer 2
|
5 | NVIC_EnableIRQ(TIM2_IRQn); |
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.
Bist du sicher, das der ClockTree des STM32 schon konfiguriert ist? Ohne alles sollte der STM32, wimre, mit dem internen RC Oszillator laufen (8MHz)?
:
Bearbeitet durch User
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.
Wo schaltest Du RCC_APB1ENR_TIM2EN an? Und beim F411 is APB1 max 50 MHz.
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
:
Bearbeitet durch User
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:
1 | // clock einschalten
|
2 | RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; |
3 | |
4 | // als alternate function konfigurieren
|
5 | GPIOA->MODER |= GPIO_MODER_MODER5_1; |
6 | |
7 | // passende AF Konfiguration in AFR schreiben
|
8 | GPIOA->AFR[0] |= (GPIO_AF1_TIM2 << (5*4)); |
Timer Setup:
1 | // Wie schon zuvor
|
2 | // enable clock to timer 2
|
3 | RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; |
4 | |
5 | // set prescaler value
|
6 | TIM2->PSC = 10000 -1; // clock = 100.000.000 Hz -> CK_PSK = 10.000 Hz |
7 | |
8 | // count to 5000
|
9 | TIM2->ARR = 5000 -1; // 10.000 Hz / 5000 = 2 Hz |
10 | |
11 | |
12 | // Ab hier dann capture compare setup
|
13 | |
14 | // 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:
1 | TIM2->CCER |= TIM_CCER_CC1P; |
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
:
Bearbeitet durch User
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.
In der Tat verrafft. Nicht selbst zusammenreimen sondern lesen würde dagegen helfen. Merci!
Null Problemo ;) Sag mal Nico, nutzt du eigentlich den 8 Mhz Quarz vom ST-Link oder hast du X3 separat bestückt?
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.
:
Bearbeitet durch User
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. :)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.