Hallo Leute,
ich versuche einen Timer dazu zu bekommen, daß er auf ein bestimmtes
Kommando von der Software her startet und einmal durchläuft. Ein
Output-Compare habe ich so eingerichtet, daß ich auf einem Pin das
Signal sehe. (Timer 5, Channel4)
Es gibt ein Beispiel unter
STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\TIM\
OnePulse, welches ich als Vorlage verwendet habe. Dort allerdings wird
der Timer durch ein Hardwareereignis (Compare Input) gestartet.
Nachdem ich alle Register des Timers hoffentlich richtig gesetzt habe,
starte ich den Timer durch TIM_Cmd(TIM5, ENABLE);
Beim ersten mal verhält er sich genau wie gewünscht: er läuft exakt
einmal durch und erzeugt dabei das gewünschte Signal.
Mein Problem ist aber, daß ich später den Timer wieder auslösen möchte
und dann geht es nicht: Beim Auslösen wechselt nur die Polarität des
Ausgangs, dann bleibt der Pegel so bis ich den Timer erneut auslöse.
Zum Wiederauslösen habe ich versucht, entweder nur TIM_Cmd(TIM5, ENABLE)
aufzurufen, oder auch die gesamte Initialisierungssequenz.
Hier ist meine Initialisierungssequenz, vielleicht seht Ihr da irgendwo
das Problem:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 15;
TIM_TimeBaseStructure.TIM_Prescaler = 2250;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
/* TIM4 PWM2 Mode configuration: Channel4 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; //16383;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC4Init(TIM5, &TIM_OCInitStructure);
/* One Pulse Mode selection */
TIM_SelectOnePulseMode(TIM5, TIM_OPMode_Single);
// TIM5 enable counter
TIM_Cmd(TIM5, ENABLE);
Hat jemand das Problem schon mal gelöst?
Vielen Dank schon mal für die Hilfe...
Grüße Ralph
Hallo Lasse
Lasse S. schrieb:> Hi,>> musst du eventuell irgendwo den aktuellen Zählstand zurücksetzen?>> Gruß> Lasse
Danke für die Antwort.
Das habe ich auch probiert. Hat nicht geholfen. Ich habe mir auch mal
die Werte aller Register des Timers ausgeben lassen (nach
Initialisierung, noch vor Start):
TIM5->CCER=0x0030
TIM5->CR1=0x0008
TIM5->CR2=0x0000
TIM5->SMCR=0x0000
TIM5->DIER=0x0000
TIM5->SR=0x0001
TIM5->EGR=0x0000
TIM5->CCMR1=0x0000
TIM5->CCMR2=0x3000
TIM5->CCER=0x3000
TIM5->CNT=0x0000
TIM5->PSC=0x08CA
TIM5->ARR=0x000F
TIM5->CCR1=0x0000
TIM5->CCR2=0x0000
TIM5->CCR3=0x0000
TIM5->CCR4=0x0000
TIM5->DCR=0x0000
Nachdem ersten Durchlauf habe ich nochmals alle Werte ausgeben lassen:
Der einzige Unterschied war das dann:
TIM5->SR=0x001F
Also der Timer selbst steht sogar auf 0. Ich habe auch versucht, das
TIM5->SR wieder auf 0x0001 zu setzten.
Grüße Ralph
Probier doch mal, UIF auch mit auf 0 zu setzen, während du die anderen
Flags im SR auch löscht, also
TIM5->SR = 0x0000;
evtl. lässt der Timer sonst keine neuen Update Events zu. Lässt du ihn
auf einen Interrupt auflaufen ?
Beispielcode und Libdoku reichen nicht aus, man sollte immer auch die
Reference studieren. Darin gibt es zum One-Pulse Mode einen eigenen
Abschnitt und dort steht:
"A pulse can be correctly generated only if the compare value is
different from the counter initial value. Before starting (when the
timer is waiting for the trigger), the configuration must be:
In upcounting: CNT < CCRx ≤ ARR (in particular, 0 < CCRx)"
Hier aber ist anfangs CNT = CCR4 = 0.
NB: Auch wenn sich die STM32Fxxx ziemlich ähneln sind sie doch nicht
identisch. Es schadet daher nicht, den Typ zu nennen.
Hallo A.K,
A. K. schrieb:> Beispielcode und Libdoku reichen nicht aus, man sollte immer auch die> Reference studieren. Darin gibt es zum One-Pulse Mode einen eigenen> Abschnitt und dort steht:>> "A pulse can be correctly generated only if the compare value is> different from the counter initial value. Before starting (when the> timer is waiting for the trigger), the configuration must be:> In upcounting: CNT < CCRx ≤ ARR (in particular, 0 < CCRx)">> Hier aber ist anfangs CNT = CCR4 = 0.
Das hatte ich auch schon gesehen, aber auch wenn ich CRR4 auf einen
anderen Wert (habe 1,8 und 15 mal probiert) setze, bleibt das
Grundproblem dasselbe.
Ich habe das Problem nun wohl ein bisschen einkreisen können: Wenn ich
z.B. CCR4=15 setze, dann stelle ich fest, daß mein Flankenwechsel beim
zweiten und weiteren Durchläufen nicht beim Start des Timers
stattfindet, sondern gemäß der Zeit, die durch CCR4 vorgegeben ist. Ist
eigentlich auch richtig so, da ich TIM_OCInitStructure.TIM_OCMode =
TIM_OCMode_Toggle vorgegeben hatte. Der erste Durchlauf ist nur deswegen
scheinbar für mich ok, weil hier wohl beim ersten Einschalten des Timers
der Ausgang auf high geht.
Was ich eigentlich erreichen möchte ist, daß der Ausgang beim Starten
des Timers auf high geht und dann beim Erreichen von CCC4 oder beim
Ablauf wieder auf low. Aber ich bekomme das mit den anderen Modes für
TIM_OCMode auch nicht hin.
> NB: Auch wenn sich die STM32Fxxx ziemlich ähneln sind sie doch nicht> identisch. Es schadet daher nicht, den Typ zu nennen.
Mein Chip ist ein STM32F103ZE mit 512kB Flash, also ein high-density
device. TIM5 ist dann wohl ein General Purpose Timer. Hardware zum
Testen ist ein Olimex Board STM32-LCD. Dort habe ich das Oszi an Pin A3
angeschlossen. Da ich dort den ersten Timerdurchlauf richtig sehe, habe
ich wohl die Initialisierung der GPIO-A richtig gemacht (auf afPushPull
und auf 10MHz, auch den Clock zur GPIO-A eingeschaltet)
Grüße Ralph
Ralph H. schrieb:> Was ich eigentlich erreichen möchte ist, daß der Ausgang beim Starten> des Timers auf high geht und dann beim Erreichen von CCC4 oder beim> Ablauf wieder auf low. Aber ich bekomme das mit den anderen Modes für> TIM_OCMode auch nicht hin.
Ich denke mit PWM Mode 1 sollte das machbar sein... gegebenen Falls die
Output Polarity auf low active einstellen.
Hallo Reinhard,
> Ich denke mit PWM Mode 1 sollte das machbar sein... gegebenen Falls die> Output Polarity auf low active einstellen.
habe es nochmals probiert, nun gehts mit:
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
Ich dachte, diese Kombination hätte ich auch schon getestet, nun ja.
Vielen Dank!
Grüße Ralph