Timer0 mit Interrupt (ATMega8) - Denkfehler im Code?

Gast #5124800
Hallo,

mein Ziel ist es timer0 für 20ms(3,6864MHz Quarz) laufen zu lassen, und 
in der ISR zu deaktivieren.
Die LED ist laut Oszi immer an. Wieso?
Ich bin für alle Hinweise und Erklärungen dankbar.

Das ist der Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "Header/timer.h"
4

5
#define TIMER0_LAEUFT     !(TIFR & (1<<TOV0))
6

7
int main(void)
8
{
9
  DDRB |= (1<<PB2);
10
  timer0_init();
11
  sei();
12

13
  while(1)
14
  {
15
    PORTB  &= ~(1<<PB2);
16
    TIMER0_START
17

18
    while(TIMER0_LAEUFT)
19
    {
20
      PORTB  |= (1<<PB2);
21
    }
22
  }
23
}
1
#ifndef HEADER_TIMER_H_
2
#define HEADER_TIMER_H_
3

4
#include <avr/io.h>
5
#include <avr/interrupt.h>
6

7
#define TIMER0_START TCCR0 |= ((1<<CS02) | (1<<CS00));  // prescaler 1024 -> 3600Hz
8
#define TIMER0_STOP TCCR0 &= ~((1<<CS02) | (1<<CS00));
9

10
void timer0_init(void);
11
ISR(TIMER0_OVF_vect);
12

13
#endif /* HEADER_TIMER_H_ */
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "../Header/timer.h"
4

5
void timer0_init(void)
6
{
7
  TCNT0 = 0x48;  // 3600Hz / 72 = 50Hz -> 20ms. TCNT0 = 0x48 (183 =255-72)
8
  TIMSK |= (1<<TOIE0);
9
  TCCR0 &= ~((1<<CS02) | (1<<CS01) | (1<<CS00));  // timer0 deaktiviert initialisieren
10
                          // mit Makro "timer0_start" (siehe timer.h) im Code starten
11
}
12

13
ISR(TIMER0_OVF_vect)
14
{
15
  TCNT0 = 0x48;  // preload Wert fuer 20ms bei 3,6kHz
16
  TIMER0_STOP
17
}
Gast #5124816
Oliver S. schrieb:
> Wenn du den Timer in deiner Hauptschleife immer wieder
> einschaltest, was
> meinst du, wie lange der nach einem Interrupt aus bleibt?
>
> Oliver
1
#define TIMER0_LAEUFT     !(TIFR & (1<<TOV0))
2

3
while(TIMER0_LAEUFT)

Diese while Schleife sollte er doch erst nach der ISR verlassen oder 
nicht?
(Firma: Vescomp) #5124842
Clemens B. schrieb:
> while(TIMER0_LAEUFT)
>
> Diese while Schleife sollte er doch erst nach der ISR verlassen oder
> nicht?

 Ja, und ?
1
    PORTB  &= ~(1<<PB2);   // LED AUS   --+ Wieviel Zeit
2
    TIMER0_START           //             | vergeht
3
                           //             | zwischen
4
    while(TIMER0_LAEUFT)   //             | diesen
5
    {                      //             | zwei
6
      PORTB  |= (1<<PB2);  // LED AN    --+ Befehlen ?
7
    }
Gast #5124879
Oliver S. schrieb:
> Clemens B. schrieb:
>> Diese while Schleife sollte er doch erst nach der ISR verlassen oder
>> nicht?
>
> Diese while-Schleife wird niemals verlassen. Die ISR funkt zwar
> dazwischen, aber danach geht's munter im while-Kreis weiter.
>
> Oliver

Ach verdammt stimmt, da ist der Denkfehler. Danke!
Gast #5124915
Ps. Für den Fall, dass es irgendwann mal jemanden hilft. Ich hab es 
jetzt so gelöst und es läuft wie erwartet:
1
#define TIMER0_LAEUFT   TCCR0 && 0x05

Kann geschlossen werden.
Danke nochmal.
Moderator (Firma: Titel) Persönliche Seite #5124938
Clemens B. schrieb:
> es läuft wie erwartet:
> #define TIMER0_LAEUFT   TCCR0 && 0x05
Tatsächlich mit dem logischen &&?
Dann wäre es das selbe wie
#define TIMER0_LAEUFT   TCCR0
(denn 0x05 ist immer "true" und kann für ein logisches Und ignoriert 
werden)
Und damit muss nur irgendein Bit im TCCR0 gesetzt sein, dass auch 
TIMER0_LAEUFT "true" ist...
Gast #5124953
Lothar M. schrieb:
> Clemens B. schrieb:
>> es läuft wie erwartet:
>> #define TIMER0_LAEUFT   TCCR0 && 0x05
> Tatsächlich mit dem logischen &&?
> Dann wäre es das selbe wie
> #define TIMER0_LAEUFT   TCCR0
> (denn 0x05 ist immer "true")
> Und damit muss nur irgendein Bit im TCCR0 gesetzt sein, dass auch
> TIMER0_LAEUFT "true" ist...

Natürlich das bitweise UND. Vorm posten prüfe ich nächstes Mal..
#5124977
@Clemens B. (Gast)

>Natürlich das bitweise UND. Vorm posten prüfe ich nächstes Mal..

Eine gute Idee. Außerdem sollte man derartige Makros IMMER mit einer 
Klammer versehen, damit es nicht zu komischen Nebeneffekten kommt, wenn 
das Makro in einem komplexeren Ausdruck eingesetzt wird und dort 
höherpriorisierte Operatoren angewendet werden. Aber deine Makro ist 
immer noch nicht wasserdicht. Warum prüfst du nicht einfach alle drei 
CSx Bits? Und wenn man es ordentlich und direkt verständlich schreiben 
will, nimmt man die Bitnamen und keine magic numbers.

Siehe Bitmanipulation und
Strukturierte Programmierung auf Mikrocontrollern.

Also eher so.
1
#define TIMER0_LAEUFT   ( TCCR0 & ((1<<CS02) | (1<<CS01) | (1<<CS00)) )
(Firma: Vescomp) #5124988
Clemens B. schrieb:
> Ps. Für den Fall, dass es irgendwann mal jemanden hilft. Ich hab es
> jetzt so gelöst und es läuft wie erwartet:
> #define TIMER0_LAEUFT   TCCR0 && 0x05
>
> Kann geschlossen werden.
> Danke nochmal.

 Was läuft wie erwartet ?

    PORTB  &= ~(1<<PB2);

 Diesen Befehl kannst du ruhig weglassen, absolut nutzlos.

 Somit ist deine LED praktisch immer an (oder aus) - je nachdem wie
 du das angeschlossen hast - wozu das Ganze ?
#5125443
Hi

Nebenfrage:

Clemens B. schrieb:
> #define TIMER0_LAEUFT     !(TIFR & (1<<TOV0))

Dieses Define wird bei jedem Aufruf im Programm erneut hergeleitet?
Hätte jetzt erwartet, daß der Wert Rechts beim Compilieren berechnet 
wird und danach Timer0_Laeuft eine Konstante ist - hätte nebenbei auch 
erklärt, warum nicht aus dem While raus gegangen wird.

Vll. sollte ich doch Mal in C rein schnuppern :/

MfG
Gast #5125707
@Falk
Da hast du vollkommen recht, die Leerzeichen zwischen den äußersten 
Klammern hatte ich vorher nie gemacht, ansonsten mache ich das identisch 
;) schöner Tipp zur besseren Lesbarkeit.
So habe ich mein define aktuell, das CS01 Bit wird bei mir nie gesetzt.
1
#define TIMER0_LAEUFT   ( TCCR0 & ((1<<CS02) | (1<<CS00)) )

@Marc
So wie Jim schon erkannt hat. Es ist ein reiner Funktionstest. Und bei 
meinem Oszi geht's bis 2ns runter, mehr als ausreichend und den Puls zu 
sehen der entsteht..

@Patrick
#define ist eine sogenannte Präprozessor Direktive:
https://de.wikibooks.org/wiki/C-Programmierung:_Präprozessor

Erhöht halt die Lesbarkeit im Code(richtig angewandt). Dazu kommt das 
was Falk geschrieben hat.
Gast #5125708
@Falk
Da hast du vollkommen recht, die Leerzeichen zwischen den äußersten 
Klammern hatte ich vorher nie gemacht, ansonsten mache ich das identisch 
;) schöner Tipp zur besseren Lesbarkeit.
So habe ich mein define aktuell, das CS01 Bit wird bei mir ja nie 
gesetzt.
1
#define TIMER0_LAEUFT   ( TCCR0 & ((1<<CS02) | (1<<CS00)) )

@Marc
So wie Jim schon erkannt hat. Es ist ein reiner Funktionstest. Und bei 
meinem Oszi geht's bis 2ns runter, mehr als ausreichend und den Puls zu 
sehen der entsteht..

@Patrick
#define ist eine sogenannte Präprozessor Direktive:
https://de.wikibooks.org/wiki/C-Programmierung:_Präprozessor

Erhöht halt die Lesbarkeit im Code(richtig angewandt). Dazu kommt das 
was Falk geschrieben hat.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.