STM32F4 TIM2-Timer, erreicht 1 Sekunde

Ich lerne ein wenig über Allzweck-Timer auf meinem STM32F4Discovery-Board und würde gerne wissen, wie ich den Timer so konfigurieren kann, dass er jede Sekunde einen Timer-Interrupt auslöst oder zumindest den Wert für das automatische Neuladen alle 1 Sekunde auf 0 zurücksetzt.

Ich weiß, dass die MCU mit 168 MHz läuft, und ich verwende die interne Uhr als TIM2-Taktquelle. Ich würde gerne besser verstehen, wie ich den entsprechenden Prescale-Wert, die Periode und die Taktteilung berechnen kann, um 1 Sekunde zu erreichen.

TIM_HandleTypeDef timeBase;
timeBase.Instance = TIM2;
timeBase.Init.Prescaler = 0;
timeBase.Init.CounterMode = TIM_COUNTERMODE_UP;
timeBase.Init.Period = 168000000; // Hypothetical value (Period cannot be greater than 65535)
timeBase.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&timeBase);

Habe ich Recht, wenn ich sage, dass das Obige mit einem Prescaler von 0, einer Periode von 168000000 und einer Taktteilung von 1 dazu führt, dass der Wert für das automatische Neuladen des Timers alle 1 Sekunde auf 0 zurückgesetzt wird?

Jetzt hat die Periode einen maximalen Wert von 0xFFFF (65535), was für mich bedeutet, dass ich den Prescaler-Wert und die Periode manipulieren muss, um ein Zurücksetzen des automatischen Neuladewerts von 1 Sekunde zu erreichen.

Gibt es dafür eine Formel?

Verwenden Sie die STM32F4-Peripheriebibliothek von ST Micro oder den STM32CubeF4 oder etwas anderes? IIRC enthält beide Code, um jede Systemuhr einzustellen und den Timer in den Auto-Reload-Modus zu versetzen. Wie Sie berechnet haben, müssen Sie sowohl den Prescaler als auch den Reload-Wert manipulieren. 168.000.000 sind ungefähr 28 Bit, also würden zwei Faktoren (Zahlen) mit jeweils ungefähr 14 Bit funktionieren, oder jedes Paar mit einem 16 Bit oder weniger und dem anderen 12 Bit oder mehr, was multipliziert 168.000.000 ergibt.

Antworten (2)

Sie haben zwei Probleme. Das erste ist, dass die MCU mit 168 MHz läuft, wenn sie so eingerichtet wurde , und Ihr Compiler tut dies möglicherweise nicht standardmäßig. Das Einstellen der Uhr ist etwas geheimnisvoll. ST bietet ein Excel-basiertes Tool, mit dem Sie eine Setup-Datei erstellen können. Anschließend muss die Datei an der richtigen Stelle abgelegt und einige andere Dateien bearbeitet werden.
Geben Sie hier die Bildbeschreibung ein

Ich empfehle diese Seite als Ort, um alle relevanten Informationen zu erhalten. Es gibt eine ST-Seite mit Anweisungen , die jedoch nicht so klar ist wie einige der anderen Tutorials.

Wenn Sie dies tun, läuft der APB1-Bus, auf dem sich TIM2 befindet, mit maximal 42 MHz, was Ihnen einen TIM2-Takt von 84 MHz gibt (er wird durch PLL verdoppelt). Wenn Sie es schneller brauchen, müssen Sie einen der Timer auf APB2 verwenden, der doppelt so schnell geht. Beachten Sie, dass dieser Bus keine 32-Bit-Timer hat.

Geben Sie hier die Bildbeschreibung ein

Das zweite Problem ist, wie Sie sagten, dass Sie einen Höchstwert überschritten haben. Ja, Sie müssen mit den beiden Werten spielen. Wenn Sie Ihre Uhr mit dem Vorteilskalar durch (42000-1) teilen, um eine Zeitbasis von 2 kHz zu erhalten, und dann die Periode auf (2000-1) einstellen, gibt es Ihr 1-Sekunden-Intervall.

Natürlich müssen Sie die UHR am TIM2-Peripheriegerät EINSCHALTEN und dann TIM2 aktivieren, sonst funktioniert nichts.

Danke für die Antwort. Das hat wirklich sehr geholfen. Ich verwende CubeMX anstelle der Excel-Tabelle, um mein Projekt zu konfigurieren, mache aber dasselbe.
Warum subtrahieren wir 1 von 42000 und 2000?
Weil es bei Null beginnt und beim Überlauf unterbricht
Duh, richtig. :) Manchmal lebe ich in einer Traumwelt. Dank dafür.

Auch wenn Sie sich nicht mit dem Einrichten der Uhr durch RCC-Register beschäftigen möchten , können Sie Ihrer Timer-Initialisierungsfunktion einfach die beiden folgenden Zeilen hinzufügen:

// This idea has been taken from "USART BRR Configuration" section in the USART_Init() function

RCC_ClocksTypeDef   RCC_ClocksStatus;
RCC_GetClocksFreq(&RCC_ClocksStatus);/*This line gives us System current frequency
Note that above function returns the frequencies of different on chip clocks; SYSCLK, HCLK,  PCLK1 and PCLK2.*/

und dann haben Sie für Prescaler und Period :

/* timer_tick_frequency for TIM4 = ( (2*APB1 frequency)/10000 )-1 */

TIM_TimeBaseInitStructure.TIM_Prescaler = (2*RCC_ClocksStatus.PCLK1_Frequency/10000-1);//Conter clock frequency (CK_CNT) is now 10KHz

TIM_TimeBaseInitStructure.TIM_Period    = (10000-1);//Update Event occurs every 1 Seconds

Wenn Sie also annehmen, dass die APB1-Frequenz 42 MHz beträgt, dann ist der Prescaler-Wert:

(2*42000000)/10000 - 1 = 8400 -1 = 8399

dann können Sie alle 1 Sekunde den IRQn-Handler durchlaufen, um zu tun, was Sie wollen.