Forum: Mikrocontroller und Digitale Elektronik [AVR] Capture Compare Timer1 kommt das erste mal zu früh?


von avr-gast (Gast)


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!

von counter (Gast)


Lesenswert?

schon ausprobiert nach TIMSK1 |= _BV(OCIE1A); mal TCNT1 = 0x0; in 
timer_attach_CCA zu setzen?

von avr-gast (Gast)


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?

von Michael A. (Gast)


Lesenswert?

avr-gast schrieb:
> 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.

Passiert das im wahren Leben oder in der Simulation?

von avr-gast (Gast)


Lesenswert?

leider im in der Realität ... :-(

von Michael A. (Gast)


Lesenswert?

avr-gast schrieb:
> leider im in der Realität ... :-(

Und im Simulator auch? Dann würden sich ja ein Ansatzpunkt ergeben.

von Stefan E. (sternst)


Lesenswert?

Du startest den Timer, während OCR1A 0 ist, damit dürfte es sofort einen 
Compare-Event geben und das entsprechende Interrupt-Flag gesetzt werden. 
Ergo wird dann auch sofort nach erlauben der Interrupts dieser ausgelöst 
werden.

von avr-gast (Gast)


Lesenswert?

Welchen Ansatzpunkt siehst du da?

Also es passiert ohne AVR JTAG und mit AVR JTAG im Debugg Modus - 
Simuliert hab ich es nicht.

von avr-gast (Gast)


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!

von avr-gast (Gast)


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 ... ;(

von Peter D. (peda)


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

von avr-gast (Gast)


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!

von Peter D. (peda)


Lesenswert?

avr-gast schrieb:
> @Flag löschen:
> Hab ich auch schon probiert klappt leider auch nicht,

Man muß die Reihenfolge genau einhalten:
timer_init:
- cli
- Timermoderegister einstellen
- Timerwerteregister laden
- Flagregister setzen (um zu löschen)
- Interruptquellen enablen
- sei


Peter

von avr-gast (Gast)


Lesenswert?

Hallo,

also es war leider wirklich ein Modul welches blöderweise rein gespielt 
hat.

Trotzdem herzlichen Dank an Peter für die nette Unterstützung!

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.