Forum: Mikrocontroller und Digitale Elektronik STM32 one-pulse-timer geht nur einmal


von Ralph H. (ralphx)


Lesenswert?

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

von Lasse S. (cowz) Benutzerseite


Lesenswert?

Hi,

musst du eventuell irgendwo den aktuellen Zählstand zurücksetzen?

Gruß
Lasse

von Ralph H. (ralphx)


Lesenswert?

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

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

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 ?

von (prx) A. K. (prx)


Lesenswert?

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.

von Ralph H. (ralphx)


Lesenswert?

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

von Reinhard B. (brainstorm)


Lesenswert?

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.

von Ralph H. (ralphx)


Lesenswert?

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

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
Noch kein Account? Hier anmelden.