www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Mit Timer2 von AVR in FW einen 16bit Timer realisieren


Autor: avr_timer2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen,

ich brauch basierend auf den Timer 2 eine Zeitbasis die aber 16bit groß 
sein muss.

Irgendwie läuft aber bei mir etwas schief so bekomme ich manchmal 
falsche Werte wie z.B. hier.
1. Wert: 0xB700
2. Wert: 0xB807
1 Tick ist 244us zw. Wert 1 und Wert 2 sind aber nur ca. 2ms vergangen 
(Oszi) => 1. Wert sollte 0xB7FF heißen (vermute ich jetzt mal g)

Das Problem tritt leider nicht sehr häufig auf ...

Timer2 macht beim Überlauf (ca. 62,5ms) einen Interrupt die Routine 
sieht so aus:
ISR(TIMER2_OVF_vect)
{
g_nOverflow_cnt++;
 while(ASSR & _BV(TCR2BUB));

  TCCR2B = TCCR2B;
}
Auslesen vom Timer2 16bit Wert sieht so aus:
uint16_t RTC_GetTickStamp(void)
{
  uint8_t tickstamp = 0;
  uint16_t retval = 0;
  do
  {
    retval = 0;
    tickstamp = TCNT2;
    retval = (g_nOverflow_cnt << 8);
  }
  while((tickstamp != TCNT2));
  retval |= tickstamp;
  return retval;
}

Während des Schreibens meines Beitrages ist mir das Problem aufgefallen, 
RTC_GetTickStamp wird in einer ISR aufgerufen, wenn nun aber der Timer2 
Interrupt auftritt wird natürlich g_nOverflow_cnt nicht erhöht.

So ich hab nun eine "safe" routine entschieden welche in interrupts 
aufgerufen wird (ich brauch das leider das ich mir den Zeitstempel merke 
wenn z.B. ein GPIO INterrupt auftritt. Nur funktioniert das auch nicht. 
Bin etwas ratlos, vlt. hat wer einen Tipp für mich? Danke!
uint16_t RTC_GetTickStamp_safe(void)
{
  uint8_t tickstamp = 0;
  uint16_t retval = 0;
  uint8_t overflow_cnt = g_nOverflow_cnt;
  uint8_t irq_happend = 0;
  /*needed for short wake up */
  OCR2A = OCR2A; //dummy write neccassary if awake time is less then 30us.
  while(ASSR & (_BV(OCR2AUB)));
  do
  {
    retval = 0;
    tickstamp = TCNT2;
    retval = (g_nOverflow_cnt);
    if(TIFR2 & _BV(TOV2))
    {
      irq_happend = 1;
    }
  }
  while((tickstamp != TCNT2) || (retval != g_nOverflow_cnt));
  retval = ((retval+irq_happend) << 8);
  retval |= tickstamp;
  return retval;
}

Danke!

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Codesammlung: "AVR Timer mit 32 Bit"


Peter

Autor: avr_timer2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

danke für deinen Tipp - löst aber nicht das Problem. Im Endeffekt hab 
ich es so wie schon diskutiert mit etwas Jitter und mehr Code gelöst 
gehabt. Deine Version ist eleganter keien Frage. Dennoch hab ich noch 
das Problem dass z.B. bei 2ms Delay 65ms Berechnet werden:
g_n_dbg_duration:0x0107
g_n_begin_tick:0x2700
g_n_end_tick:0x2807

das ist der Tickstamp, also der 16bit Timerwert. ich sag mal das ist 
hier ein schönes beispiel ich glaub das g_n_begin_tick 0x2800 sein 
sollte.

Hier mal mein Codeteil von dir übernommen:
uint16_t RTC_GetTickStamp(void)
{
  uint8_t tmp_sreg;
  uint16_t retval = 0;
  uint8_t irq_happend = 0;
  tmp_sreg = SREG;
  cli();
  retval = g_nOverflow_cnt + TCNT2;
  irq_happend = TIFR2;
  SREG = tmp_sreg;

  if((irq_happend & _BV(TOV2)) && !(retval&0x80))
  {
    retval += 256;
  }

  return retval;
}

So hab ich es jetzt cli/sreg hab ich etwas umgeschrieben weil es bei mir 
vorkommen kann das das GIE Flag gelöscht ist.

Also ich hab auch in meinem Codeteil keinen Fehler gefunden und deiner 
scheint auch sehr schlüßig zu sein, die Frage ist nun für mich warum 
funktioniert es bei mir trotzdem nicht?

Etwas mehr Hintergrundinfos von meinem Projekt:
Ich lege den Controller auch immer Schlafen fast immer in PWR_SAVE und 
manchmal IDLE. Könnte es event. damit zu tun haben?
void sch_go_into_sleep_mode(void)
{
  // sleep
  RTC_Wait();
  set_sleep_mode(_sleep_mode);
  cli();
  sleep_enable();
  sei();
  sleep_cpu();
  sleep_disable();
}

void RTC_Wait(void)
{
  OCR2A = OCR2A; //dummy write neccassary if awake time is less then 30us.
  while(ASSR & (_BV(OCR2AUB)));
}

_sleep_mode ist entweder PWR_SAVE oder  IDLE je nach Betriebszustand von 
mir (UART aktiv IDLE, ansonsten PWR_SAVE). Ich mess aber dzt. zu 99% nur 
im PWR_SAVE zustand.

Hast du vielleicht eine Idee woran es sonst liegen könnte bzw. Tipp?

Danke!

Autor: avr_timer2 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So ich glaub ich hab das Problem gefunden, hab das wie folgt abgeändert:
uint16_t RTC_GetTickStamp(void)
{
  uint8_t tmp_sreg;
  uint16_t retval = 0;
  uint8_t irq_happened = 0;
  tmp_sreg = SREG;
  cli();
  retval = g_nOverflow_cnt + TCNT2;
  TCCR2B = TCCR2B;
  while(ASSR & (1 << TCR2BUB))
  irq_happened = TIFR2;
  SREG = tmp_sreg;

  if((irq_happened & _BV(TOV2)) && !(retval&0x80))
  {
    retval += 256;
  }

  return retval;
}

Übrigens ist bei peda ein kleines typo im code drin es müsste für den 
Teimer 2 TIFR2 heißen - im Codeschnippel ist TIFR. aber das nur am Rande 
bemerkt.

Danke nochmal an peda für den input der eleganten Version!

Falls es doch nicht die LÖsung war melde ich mich wieder - versprochen 
;)

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Übrigens ist bei peda ein kleines typo im code drin es müsste für den
>Teimer 2 TIFR2 heißen - im Codeschnippel ist TIFR. aber das nur am Rande
>bemerkt.

Es gibt AVRs, die für alle Timer nur ein TIF-Register haben. Und das 
heisst dann auch nur TIFR.

MfG Spess

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.