Hallo,
ich versuche auf einem STM32F4 Discovery Board ein PWM Signal (siehe
Anhang) mit 16 Wiederholungen zu erzeugen. Dabei sollen die Pulsweiten
einzeln vorgegeben werden. Hier meine Timer Initialisierung:
/* Generate an update event to reload the Prescaler and the repetition counter value immediately */
32
TIM3->EGR=TIM_EGR_UG;
33
TIM3->RCR=16-1;//Set the Repetition counter value
34
/* TIM3 enable counter */
35
TIM_Cmd(TIM3,ENABLE);
36
}
Mit dieser Initialisierung wird nur ein ganz normales PWM Signal mit der
Frequenz von 595kHz erzeugt ohne Unterbrechung obwohl das Register RCR
auf 15 gesetzt ist.
Ich weiss nicht wie die Pulsbreite einzeln vorgegeben werden kann.
Weiss jemand zufällig wie man das macht?
Danke!
Väinö schrieb:> Ich weiss nicht wie die Pulsbreite einzeln vorgegeben werden kann.> Weiss jemand zufällig wie man das macht?
Einzeln kannst du die nicht vorgeben. Du kann halt [RepetitionCounter] x
Impulse mit festem Tastgrad erzeugen.
Für deinen Fall:
Repetition Counter = 1 => Tastgrad 75%
Repetition Counter = 5 => Tastgrad 25%
Repetition Counter = 1 => Tastgrad 75%
Repetition Counter = 1 => Tastgrad 25%
usw... Du musst es quasi halb zu Fuß machen!
Es geht mit Hilfe von DMA auch mit variabler Periodendauer. Guck mal in
AN4776 ("general purpose timer cookbook") unter "arbitrary waveform
generator".
Sehr interessant, gleich mal gespeichert die AppNote, danke!
Dann kann man damit Neopixel ohne CPU Auslastung befeuern? Genial!!!
Gerade gesehen, man könnte sogar den Prescaler gleich mit ändern. Da
sind die Möglichkeiten ja grenzenlos!
Christopher J. schrieb:> Es geht mit Hilfe von DMA auch mit variabler Periodendauer. Guck> mal in> AN4776 ("general purpose timer cookbook") unter "arbitrary waveform> generator".
Danke für die Antworten. Ich versuche vergeblich diese zu
implementieren. Leider klappt es bei mir nicht. Ich sehe nur ein ganz
normales PWM Signal, ohne Unterbrechung. Wenn ich OPMode auf
TIM_OPMode_Single setze, sehe ich am PWM Ausgang nichts.
Weiss jemand zufällig woran es liegt?
Danke im Voraus.
wie Ingo L. vorgeschlagen, TIM_OPMode_Single Mode nehmen.
Bei Init TIM_TimeBaseStructure.TIM_RepetitionCounter = 15 setzen. Gilt
nur für Timer 1 und 8, Nicht am Ende der Init an den Registern fummeln
Vielen Dank für den Hinweis. Ich kann jetzt gewünschte 16
Rechtecksignale generieren. Allerdings klappt es mir nicht die einzelnen
PWM Duty Cycles zu setzen.
Frank B. schrieb:> Der Datentyp deines Arrays und der Datentyp in MemoryDataSize> passen> schonmal nicht zusammen.
Vielen Dank für den Hinweis. Ich hab es geändert, das bringt leider
keine Verbesserung. :(
Moin,
TIM1->CCR1 ist 16bit gross, weil TIM 1&8 16bit Timer sind.
Dein Array ist 32bittig.
Aus dem RM:
17.2 TIM1&TIM8 main features
TIM1&TIM8 timer features include:
• 16-bit up, down, up/down auto-reload counter.
• 16-bit programmable prescaler allowing dividing (also “on the fly”)
the counter clock
frequency either by any factor between 1 and 65536.
• Up to 4 independent channels for:
– Input Capture
– Output Compare
– PWM generation (Edge and Center-aligned Mode)
– One-pulse mode output
Läuft denn der DMA durch?
Den HAL benutze ich nicht. Wo stellt man denn hier die Anzahl an
DMA Transfers ein?
Darth Moan schrieb:> Den HAL benutze ich nicht. Wo stellt man denn hier die Anzahl an> DMA Transfers ein?
... er benutzt den HAL ebenfalls nicht :-)
Das sind SPL-Aufrufe ... (SPL = standard peripheral library)
Viele Grüße
Igel1
Und wenn Du ganz genau wissen willst, wie's funktioniert, so lies Dir
das Codebeispiel aus der Peripheral Library durch.
Es macht exakt das, was Du umsetzen möchtest: variable Duty-Zyklen,
realisiert via DMA-Schreibvorgängen in das CCR-Register.
Das Beispiel findet sich gemeinerweise nicht im DMA-Beispiel-Ordner,
sondern im TIM-Beispielordner:
STM32F4xx_DSP_StdPeriph_Lib_V1.8.0\Project\STM32F4xx_StdPeriph_Examples\
TIM\TIM_DMA
Viele Grüße
Igel1
Andreas S. schrieb:> Und wenn Du ganz genau wissen willst, wie's funktioniert, so lies Dir> das Codebeispiel aus der Peripheral Library durch.>> Es macht exakt das, was Du umsetzen möchtest: variable Duty-Zyklen,> realisiert via DMA-Schreibvorgängen in das CCR-Register.
Hallo Andreas,
Vielen Dank!!!. Die Beispiele der Standard Peripherie Lib sind bei mir
aus dem Jahr 2011 :D. Da sind keine solche Beispiele vorhanden.
Gruss,
Väinö
Dann lade dir halt mal die aktuelle Version runter:
http://www.st.com/resource/en/firmware/stm32f4_dsp_stdperiph_lib.zip
Da sind zwei Beispiele drin:
TIM_DMA verändert nur den Dutycycle per DMA und die Periodendauer bleibt
konstant
TIM_DMABurst verändert sowohl Dutycycle, als auch Periodendauer
Ach ja, und noch etwas:
Du hast diese Zeile in Deinem Code:
1
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
Damit wird Dein CCR1 immer erst nach einem Update Event [UEV] neu mit
dem Preload-Wert befüllt. Das ist im Normalfall auch völlig korrekt,
denn Du willst CCR1 ja immer erst neu setzen, wenn der Counter CNT
einmal bis zum ARR-Wert durchgelaufen ist (sprich: das neue CCR1 soll
erst im nächsten Zyklus gültig werden).
Das Problem: bei gesetztem Repetition-Register (was bei Dir 15 statt 1
lauten müßte (siehe "Buffer"), damit die DMA 16 Werte übertragen werden)
passiert so ein Update Event erst nachdem das TIMx_RCR-Register auf 0
geht.
Will sagen: auch wenn Dein DMA schön in das CCR1-Register schreibt - es
landet alles nur im Preload-CCR1-Register und wird erst am Ende der
OnePulse-Sequenz in das echte CCR1-Register geschrieben.
Also Preload abschalten via:
Dann funktioniert's zwar, aber Du hast nun ein anderes Problem:
Wenn Du z.B. aufsteigende Werte per DMA in CCR1 schreibst (z.B. 50,
120), so wird Dein DMA 2x in einem Timerlauf getriggert, bevor der
Timer-Counter den Auto Reload Register-Wert erreichen kann: nämlich bei
50 und kurz darauf bei 120). Du kannst also nur streng monoton fallende
Duty-Cyclen realisieren (im Falle von PWM2-Mode) oder streng monoton
steigende Duty-Cyclen im Falle von PWM1-Mode.
Will sagen: der verfolgte Ansatz mit dem OnePulse-Mode und dem
Repetition-Register ist vermutlich ungeeignet für Dein Ziel.
Viele Grüße
Igel1
Das Timer-Signal liegt am Ausgang PA8 an.
Auf dem STM32F4 Board einfach PA8 mit PD12 verbinden - dann zeigt die
grüne LED die Pulse an.
Periode der Pulse ist 1s.
Der Duty-Cycle wird über das Array "TIM1_PWM_Values[16]" bestimmt.
Entgegen meiner Voraussage aus dem vorigen Post, funktioniert das
Programm auch mit aufsteigenden oder gar springenden Array-Werten
(jedenfalls auf den ersten Blick). Einen Reim kann ich mir gerade nicht
darauf machen. Müßte ich mir dem dem Oszi nochmals näher angucken -
allein mir fehlt gerade der "Schnuff".
Viele Grüße
Igel1