[AVR] Capture Compare Timer1 kommt das erste mal zu früh?

Gast #2243600
Lesenswert?

Hallo,

ich hab ein etwas seltsames Verhalten:
Beim ersten  Mal nach dem Reset vom AVR wird der CCA vom Timer1 zu früh 
ausgelöst, danach scheint es immer korrekt zu laufen.
Es dürfte wohl in der Initialisierung etwas faul sein... nur komme ich 
nicht drauf, hat wer einen Tipp für mich?


Hier der Code vom Starten des Timers:
void timer_init(void)
{
  timer_reset();
  TCCR1B = (TCCR1B & ~T1_PRESCALE_MASK) | T1_PRESCALE;
}

void TIM_reset(void)
{
  TIMSK1 &= ~_BV(OCIE1A);
  TIMSK1 &= ~_BV(OCIE1B);
  OCR1A = 0;
  OCR1B = 0;
  TCNT1 = 0;
}

Interrupt aktivieren an CCA:
uint8_t timer_attach_CCA(uint16_t count, void(*callback)(void))
{
  uint16_t value = count;

  if(callback_CCA)
  {
    return T1CCA_RESERVED;
  }

  value = value + TIM_Get_Value1();
  OCR1A = value;
  callback_CCA= callback;
  TIMSK1 |= _BV(OCIE1A);
  return T1_OK;
}

ISR(TIMER1_COMPA_vect)
{
  TIMSK1 &= ~_BV(OCIE1A);
  if (callback_CCA)
  {
    callback_CCA();
  }
  callback_CCA=0;
}

In der Applikation wird dann timer_attach_CCA aufgerufen, wie gesagt 
beim ersten Mal wird die Funktion(callback) fast sofort ausgeführt ca. 
20 Timerticks später, bei den Nachfolgenden exakt zu dem Eingstellten 
Zeitpunkt. (Habs mit Oszi und AVR Debugging versucht einzugrenzen nur 
komme ich nicht auf das Problem)

Danke!
Gast #2243631
Lesenswert?

Hmm nein aber das möchte ich ja nicht, weil es kann auch sein das am CCB 
(selbiger Code wie CCA) ein Event hängt und das würde dann verfälscht, 
verlängert, ... werden.

Ist dies leicht nötig?
Gast #2243718
Lesenswert?

@Stefan:

Danke für den Hinweis, leider ist es das auch nicht, ich hab z.B.
void TIM_reset(void)
{
  TIMSK1 &= ~_BV(OCIE1A);
  TIMSK1 &= ~_BV(OCIE1B);
  OCR1A = 0;
  OCR1B = 0;
  TCNT1 = 1;
}

gesettzt bei meiner Takrate sollte erst in 1 sek. ein Überlauf 
auftreten, trotzdem gehts es nicht.

Hier geht es um ein Zeitfenster von ca. 15ms.

Noch einen Nachtrag:
Ich stoppe den Timer immer zwischen durch mit
void timer_stop(void)
{
TCCR1B = (TCCR1B & ~TIM_PRESCALE_MASK) | TIM_CLK_STOP;
}

(wegen den Power Modi)

und starte diesen dann wieder mit timer_init();

d.h. eigentlich sind es immer die selben Ausgangsbedingungen trotzdem 
gibts nach dem Reset diese "komische" Verhalten.

also ungefähr so:
void cca_function()
{
 timer_stop();
 ...Ich mache etwas...
}

void app(void)
{
...
if(Bedingung)
{
timer_init();
timer_attach_CCA(15ms, cca_function);
}
...
}
Fällt noch jemanden etwas ein, bin mir sicher das ist eine Kleinigkeit 
die ich Übersehe...

Danke!
Gast #2243793
Lesenswert?

Hab im Datenblatt zwar was gefunden, nur leider hilft das auch nichts:

###
Since writing TCNTn in any mode of operation will block all compare 
matches for one timer clock
cycle, there are risks involved when changing TCNTn when using any of 
the Output Compare
channels, independent of whether the Timer/Counter is running or not
###

Hmm schön langsam verzweifle ich ... ;(
#2243881
Lesenswert?

Generell sollte man erstmal den MC zu nennen. Es gibt viele AVR-Typen 
und die Timer sind unterschiedlich.

avr-gast schrieb:
> Noch einen Nachtrag:
> Ich stoppe den Timer immer zwischen durch mit
> void timer_stop(void)
> {
> TCCR1B = (TCCR1B & ~TIM_PRESCALE_MASK) | TIM_CLK_STOP;
> }
>
> (wegen den Power Modi)

Stop spart keinen Strom.
Manche AVRs können aber den Takt von einiger Peripherie abschalten.

Wenn es darauf ankommt, dann löscht man erstmal das Pending-Flag, bevor 
man einen Interrupt freigibt.
Es kann ja schon durch ne frühere Bedingung gesetzt worden sein.
Bei AVRs mit PLL-fähigem Timer zwischen Löschen und Freigeben noch 3 
Zyklen warten!

AVR-Fallgrube Nr.1: Pending-Flags setzen, um sie zu Löschen !!!


Peter
Gast #2243896
Lesenswert?

Hallo Peter,

danke für dein Feedback

@Stop:
Doch weil Timer 1 nur im IDLE Modus läuft und ich aber auf PWR_SAVE 
gehe.

@Controller:
Puh stimmt hab ich ganz vergessen, sorry! ATmega1284P

@Flag löschen:
Hab ich auch schon probiert klappt leider auch nicht, danke für dne 
Hinweis ich bin hinein getappt aber leider bringt es umgekehrt auch 
nichts....

Ich mach jetzt mal ein komplettes cleanes Projekt und teste das Modul 
einzeln, das Projekt ist doch schon ziemlich groß und event. Funkt da 
etwas dazwischen ... (anders kann ich es mir nicht mehr vorstellen)

Ich melde mich dann wieder, danke!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren