Hallo,
ich möchte gerne unterschiedliche Frequenzen mit dem STM32-Controller
erzeugen und dafür einen Timer im OC-Modus nutzen und auf die
HAL-Bibliothek zurückgreifen.
Irgendwie stehe ich dabei aber auf dem Schlauch, wie ich nun erstens den
Registerwert des Timers auslesen kann und zweitens einen definierten
Wert auf das OC-Register draufaddieren kann, damit der Timer nach einer
definierten Zeit erneut auslöst.
Funktional ist es so aufgebaut:
1
*briefThisfunctionhandlesTIM1globalInterrupt.
2
*/
3
voidTIM4_IRQHandler(void)
4
{
5
/* USER CODE BEGIN TIM1_IRQn 0 */
6
7
/* USER CODE END TIM1_IRQn 0 */
8
HAL_TIM_IRQHandler(&htim1);
9
/* USER CODE BEGIN TIM1_IRQn 1 */
10
11
/* USER CODE END TIM1_IRQn 1 */
12
}
Der eigentliche HAL_TIM_IRQHandler(&htim1) liegt in der HAL-Bibliothek
"stm32f4xx_hal_tim.c" und soll nicht verändert werden!
Das ist eine gesetzte Anforderung, die ich als gegeben hinnehmen muss.
Um mein Vorhaben um zu setzen, muss ich folglich meine Modifikation im
Usercode vor oder nach dem Aufruf der Funktion einbringen und neue Werte
in die OC Register schreiben bzw. durch Vergleich mit dem Zählerwert
erstmal berechnen, was da nun reingehört.
Nun stellen sich mir da zwei Schwierigkeiten in den Weg:
1. Woher weiß ich am Punkt des Usercodes, welcher Channel nun den OC
Interrupt ausgelöst hat?
Welche Funktion aus der HAL-Bibliothek könnte ich dafür nutzen, um diese
Information zu bekommen?
2. Mit welcher Funktion kann ich den aktuellen Stand des OC Registers
sowie den aktuellen Stand des Timers auslesen?
Da ich alle 4 Kanäle gelichzeitig nutze, möchte ich den Timer permanent
hochzählen lassen und immer wenn der jeweilige IR auslöst für den
zugehörigen IR eine Konstante auf den OC wert drauf addieren.
Kann mir da einer auf die Sprünge helfen?
...ist der beschriebene Weg irgendwie untypisch, dass ich da keine
einfache Lösung in der HAL Bibliothek finde?
Was ich Kurzform möchte:
Lese in der ISR das OCR (Auslösewert) und das CR (Zählerstand), schreibe
den Wert OCR_NEU+CR in das OCR Register und definiere damit den nächsten
Auslösezeitpunkt.
Ich kann mir nicht vorstellen, dass dies mit der HAL Bibliothek nicht
einfach möglich sein sollte.
Wie erreiche ich mit den gegebenen Mitteln dieses Ziel am ehesten, oder
muss ich dafür irgendeine andere Betriebsart des Zählers wählen?
STM32 schrieb im Beitrag #4763641:
> Ich kann mir nicht vorstellen, dass dies mit der HAL Bibliothek nicht> einfach möglich sein sollte.
Ob du dir etwas vorstellen kannst oder nicht, ist (frei nach Einstein)
dem Universum schnurz.
Deine Vorgabe, daß da irgend eine ominöse Interruptfunktion aus einer
noch ominöseren HAL-Bibliothek unbedingt zu verwenden sei, ist
Mumpitz. Entweder du kippst das ganze Konzept und stellst es auf
richtige Füße oder du solltest es besser bleiben lassen.
Die allermeisten STM32 haben so reichlich an Timern, daß du für vier
Ausgangskanäle jeweils einen separaten Timer verwenden kannst. Die
brauchen dann nicht mal einen Interrupt, denn das Durchschalten auf
einen Pin geht bei m.W. allen Timern.
btw: Was stellst du dir eigentlich unter HAL (Hardware Abstraction
Layer) vor? Soweit ich das sehen kann, erledigt weder die unsägliche
ST-Lib noch diese ominöse HAL-Lib etwas derartiges. Eine echte
HW-Abstraktion geht so, daß die Schnittstelle zum aufrufenden Programm
hardwareunabhängig ist, also daß man sich da nicht drum scheren muß, was
für HW drunter liegt. Bei Speichermedien (SD z.B.) wäre das das Lesen
und Schreiben von Sektoren im zugehörigen logischen LW, bei seriellen
Verbindungen wäre das das schiere Senden und Empfangen von Daten und
ggf. das Einstellen von Baudraten und sonst NICHTS! Aber hier? Da soll
angeblich etwas abstrahiert werden und du mußt dennoch die HW anfassen -
entweder direkt oder indirekt. Das ist keine HAL. Also laß diesen
Schmonz einfach weg, befasse dich mit den Registern der Hardware direkt
und mache damit, was du eigentlich tun mußt.
W.S.
Hallo,
Danke für die Antwort, obgleich du ja augenscheinlich die HAL garnicht
einsetzt.
HAL steht für Hardware Abstraction Layer, das ist richtig. Bei den
meisten Elementen der Controller kommt man damit auch relativ einfach
zum Ziel und wie beschrieben hatte ich gehofft, dass der Anwengungsfall
einen variablen Wert auf das OCR drauf zu addieren ein bin meinen Augen
typisches Szenario wäre, so dass ich diese Aufgabe gerne mit der HAL
erschlagen hätte.
Vielleicht hat ja jemand tatsächlich genügend Erfahrung in der Anwendung
der HAL, dass mein Anliegen damit ev. doch gelöst werden kann?
STM32 schrieb im Beitrag #4763588:
> ich möchte gerne unterschiedliche Frequenzen mit dem STM32-Controller> erzeugen und dafür einen Timer im OC-Modus nutzen und auf die> HAL-Bibliothek zurückgreifen.
Nun schau mal ins Datenblatt. Da gibt es "nicht" allzuviele Register.
z.B. Timer 1:
1
TIM1->ARR;//(auto) preload register, Periode
2
TIM1->CNT;//der counter!
3
TIM1->PSC;//Teiler, zusätzlich gibt es noch einen clock divisor
4
TIM1->CCR1bis4;//duty, Tastgrad
Wie man hier unschwer erkennen kann, lässt sich mit einen Timer nur
"eine" Periode erstellen und dafür aber 4 verschiedenen duty cycle.
> Ich kann mir nicht vorstellen, dass dies mit der HAL Bibliothek nicht> einfach möglich sein sollte.
Geht schon. Nur dann muss man 2 mal die Datenblätter lesen. Wozu!?
Wenn man schon bei Einstein sind: Man sehen, ob er sich mit der
menschlichen Dummheit geirrt hat.
W.S. schrieb:> Also laß diesen> Schmonz einfach weg, befasse dich mit den Registern der Hardware direkt> und mache damit, was du eigentlich tun mußt.
Wie Recht du hast...
Aber die heutigen "Bachelors" und "Master" (die sich übrigens allesamt
für vollwertige Ingenieure halten...) mögen die Hardware nicht und auch
das Datenblatt lesen (bzw. im nächsten Schritt sogar zu verstehen) ist
viel zu kompliziert und viel zu viel verlangt. Da soll alles schön
einfach per Bibliothek / HAL ansprechbar sein ansonsten können die
Jünglinge damit nichts anfangen.
aSma>> schrieb:> Wie man hier unschwer erkennen kann, lässt sich mit einen Timer nur> "eine" Periode erstellen und dafür aber 4 verschiedenen duty cycle.
Wenn man so blind durch die Datenblätter läuft, kann man auch gleich
wieder HAL verwenden.
Pro OCR kann man bei freilaufendem Timer eine Frequenz erzeugen -
geschickterweise mit direktem Registerzugriff, wie es W.S. angedeutet
hat.
Man muss auch ehrlich sein. Die Timer sind schon ein wenig komplex. Es
gibt halt sehr viele Einstellungsmöglichkeiten, deswegen gibt es auch
Appnotes: AN2581 (stm32f10x)
Mit "oc toggle" (siehe Beispiele ST) kannst in der ISR pro timer 4
verschiedene Frequenzen/Perioden erzeugen.
m.n. schrieb:> Pro OCR kann man bei freilaufendem Timer eine Frequenz erzeugen
hehe, da knurrt der Blindenhund!
Also, das übliche Szenario ist ja so, daß man einen Vorteiler hat, der
irgend einen verdammten Takt abkriegt und seinerseits das eigentliche
Timer-Register mit seinem Output taktet. Parallel zu diesem
Timer-Register können dann 1 oder mehrere Vergleichsregister liegen, die
man mit Werten laden kann und die eine Schaltaktion auslösen, wenn das
Timer-Register gleich oder größer wird als so ein Vergleichsregister.
So.
Das ganze ist also zyklisch, also kann man erstmal nur mehrere Signale
unterschiedlicher Phasenlage erzeugen, aber keine unterschiedlichen
Frequenzen! Das könnte man nur dadurch, daß man mit jeder Schaltaktion
per Interrupt das Vergleichsregister neu setzt - ABER: ob sowas
überhaupt geht, hängt davon ab, wie die Vergleichsoperation im Detail
funktioniert. Ist sie statisch auf Gleichheit, dann geht es, sonst
nicht, weil man sonst ja mit dem Neusetzen sich das Ausgangssignal
kaputtmacht.
Genau deshalb hatte ich dem TO nahegelegt, für jeden seiner Ausgänge
einen separaten Timer zu verwenden.
W.S.
W.S. schrieb:> m.n. schrieb:>> Pro OCR kann man bei freilaufendem Timer eine Frequenz erzeugen>> hehe, da knurrt der Blindenhund!
Was hast Du denn gestern gegessen, daß Du jetzt knurren mußt.
> Genau deshalb hatte ich dem TO nahegelegt, für jeden seiner Ausgänge> einen separaten Timer zu verwenden.
Völlig überflüssig; Du hast das Datenblatt vom STM32xxx nicht gelesen!
STM32 schrieb im Beitrag #4763588:
> Da ich alle 4 Kanäle gelichzeitig nutze, möchte ich den Timer permanent> hochzählen lassen und immer wenn der jeweilige IR auslöst für den> zugehörigen IR eine Konstante auf den OC wert drauf addieren.>> Kann mir da einer auf die Sprünge helfen?
Mache es so! Damit gehen Perioden von einigen µs bis zu x-beliebigen
großen Zeiten. Programmbeispiele habe ich leider nur für AVR8, falls Du
Interesse hast.