Noob braucht Hilfe bei Timerinterrupt in C

OP #3134488
Auch ich muss euch mit Anfängerfragen belästigen und diese hier ist 
besonders lächerlich :)

Ich bekomme es nämlich einfach nicht hin, in C(GCC) ein Programm zu 
schreiben, dass den Timer0 dazu bringt, Overflow-Interrupts auszulösen. 
Als µC dient mir der ATmega8 (Ja ja, Cliché-Controller und veraltet, ich 
weiß). Meine Überlegungen:
1
#include <avr/interrupts>
der muss doch sicher rein
1
SREG |= 0b10000000
globale Interrupts einschlaten, oder kann ich da direkt
1
sei()
nehmen?
1
TOIE0 |= 0b00000001
Interrupt zulassen, geht das so?
1
TCCR0 = 0b00000101
Timer mit Prescaler 1024 einschalten, richtig?
1
ISR (TIMER0_OVF_vect)
2
{
3
  PORTD0=0b00000001   //Led anschalten
4
}
So die ISR?

Ich danke euch schon mal.

Edgar
OP #3134510
Gerne.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/delay.h>
4

5
int main(void)
6
{  
7
  DDRD = 0b11111111;
8
  SREG |= 0b10000000;
9
  TOIE0 |= 0b00000001;
10
  TCCR0 = 0b00000101;
11
  
12
    while(1)
13
    {
14
    _delay_ms(100);      //Trödeln
15
    PORTD = 0b00000000;    //Led ausschalten
16
    }
17
  
18
  ISR (TIMER0_OVF_vect)
19
  {
20
    PORTD=0b00000001;     //Led anschalten
21
  }
22
}
Mir ist auch klar, dass die LED immer nach einer unterschiedlichen Zeit 
wieder aus geht, aber das ist mir derzeit egal.
#3134523
> SREG |= 0b10000000;
-Interrupts schaltet mal mit "sei()" an.
-am SREG brauchst du nicht rumfummeln

> TOIE0 |= 0b00000001;
TOIE0 ist ein Bit im Register TIMSK
also:
1
TIMSK |= (1<<TOIE0);
>TCCR0 = 0b00000101;
besser leserlich:
1
TCCR0 = (1<<CS2) | (1<<CS0);
>  ISR (TIMER0_OVF_vect)
>  {
>    PORTD=0b00000001;     //Led anschalten
>  }
Die ISR gehört nicht IN die main-funktion
Gast #3134525
Warum nicht einfach so:
1
ISR (TIMER0_OVF_vect)
2
  {
3
  i++;
4
  PORTD=i     
5
  }

Dann passiert das an und aus ganz von selbst, und für die acht Pins am 
Port sogar mit unterschiedlichen Frequenzen.

Im AVR-GCC-Tutorial sind übrigens viele schöne Beispielprogramme. 
Studier mal jenes im Abschnitt "Overflow Interrupt", dann dürfen sich 
einige Fragen von selbst beantworten.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR

PS: Und benutz (auch in Deinem eigenen Interesse) die Bitnamen - dazu 
hat man sie erfunden.
OP #3134536
Sehe ich das richtig, wenn ich
1
TIMSK |= (1<<TOIE0)
 als "Schiebe eine 1 an TOIE0 und verknüpfe ODER-weise" und nicht als 
"Schiebe eine 1 so oft nach links, wie der Wert von TOIE0 ist" 
interpretiere?
Das würde so einiges erklären...
Gast #3134555
>Entschuldige die Unhöflichkeit...

Wenn Du bis zum ^-Operator gelesen hättest, dann würde 90% Deines Codes 
vom ersten Posting ganz anders aussehen. Spar Dir also die Sprüche und 
die Entschuldigungen. Das Ganze ist nur noch lächerlich.
OP #3134569
>...diese hier ist
>besonders lächerlich

Gebe ich zu...
Ich gebe auch zu das nicht ganz gelesen bzw. verstanden zu haben, doch 
das ich diesen Artikel kenne hätte man sich denken können (von mir aus 
auch mit dem Beispiel SREG |= 0b10000000;), weshalb sein Beitrag das 
alles hier nicht weiterbringt.



Der derzeitige Code sieht so aus:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/delay.h>
4

5
int main(void)
6
{  
7
  DDRD = 0b11111111;
8
  sei();
9
  TIMSK |= 0b00000001;
10
  TCCR0= (1<<CS00)|(1<<CS02);
11
  
12
    while(1)
13
    {
14
    _delay_ms(100);      //Trödeln
15
    }
16
}
17

18
ISR (TIMER0_OVF_vect)
19
{
20
  PORTD ^= (1<<PD0);     //Led togglen
21
}

Edgar
OP #3134628
Nachtrag an alle Anfänger, die das gleiche Problem hatten: Statt
1
TIMSK |= 0b00000001;
bitte
1
TIMSK |= 1<<TOIE0;
schreiben, denn das ist, wie Vuvuzelatus schon geschrieben hat, 
übersichtlicher.

>Vuvuzelatus schrieb:
>PS: Und benutz (auch in Deinem eigenen Interesse) die Bitnamen - dazu
>hat man sie erfunden.

Ich spiele jetzt einfach mal Moderator und mache den Thread zu, da alles 
geklärt wurde.

---------------------------Thread zu!---------------------------
#3134662
edgar 339 schrieb:
> als "Schiebe eine 1 an TOIE0 und verknüpfe ODER-weise" und nicht als
> "Schiebe eine 1 so oft nach links, wie der Wert von TOIE0 ist"
> interpretiere?
> Das würde so einiges erklären...
So kann man das interpretieren.
Tatsächlich wird natürlich mit dem Wert geschoben, mit dem TOIE0 
definiert ist. Aber nicht auf dem Controller sondern das macht der 
Compiler auf der 3-GHz-Quadcore-Granate unter dem Tisch.

mfg.
OP #3134667
Gut, danke das das nochmals geklärt wird. Im Artikel Bitmanipulation 
steht nämlich "(1 << n) : Zuerst wird durch die '<<'-Ausdrücke eine "1" 
n-mal nach links geschoben.", es wäre besser wenn es "...auf Bit n 
geschoben." lauten würde.

Edgar
#3134725
edgar 339 schrieb:
> Gut, danke das das nochmals geklärt wird. Im Artikel Bitmanipulation
> steht nämlich "(1 << n) : Zuerst wird durch die '<<'-Ausdrücke eine "1"
> n-mal nach links geschoben.", es wäre besser wenn es "...auf Bit n
> geschoben." lauten würde.

Das erste ist (allgemein gesehen) richtig.
das zweite ist deine Interpretation, die in diesem Fall (eine 1 wird 
geschoben) auf dasselbe rausläuft.
Gast #3134726
Mein Vorschlag für eine erschöpfende, nicht missverstehbare Auskunft 
darüber, was 1<<n ist:

1<<0 = 0b00000001 = 0x01 = 2^0 = 1
1<<1 = 0b00000010 = 0x02 = 2^1 = 2
1<<2 = 0b00000100 = 0x04 = 2^2 = 4
1<<3 = 0b00001000 = 0x08 = 2^3 = 8
1<<4 = 0b00010000 = 0x10 = 2^4 = 16
1<<5 = 0b00100000 = 0x20 = 2^5 = 32
1<<6 = 0b01000000 = 0x40 = 2^6 = 64
1<<7 = 0b10000000 = 0x80 = 2^7 = 128

wobei das ^ die Potenzierung bezeichnet ("hoch").
OP #3135159
>Das erste ist (allgemein gesehen) richtig.
Aber auch nur, wenn man keine Bitnamen einsetzt...

>1<<0 = 0b00000001 = 0x01 = 2^0 = 1
>1<<1 = 0b00000010 = 0x02 = 2^1 = 2
>1<<2 = 0b00000100 = 0x04 = 2^2 = 4
>1<<3 = 0b00001000 = 0x08 = 2^3 = 8
>1<<4 = 0b00010000 = 0x10 = 2^4 = 16
>1<<5 = 0b00100000 = 0x20 = 2^5 = 32
>1<<6 = 0b01000000 = 0x40 = 2^6 = 64
>1<<7 = 0b10000000 = 0x80 = 2^7 = 128

Das falsch zu verstehen wird wirklich schwer :D
Wirklich gute Idee!
#3135747
edgar 339 schrieb:
>>Das erste ist (allgemein gesehen) richtig.
> Aber auch nur, wenn man keine Bitnamen einsetzt...

Die "Bitnamen" sind auch nichts weiter als Präprozessor-Makros, für die 
eine Zahl eingesetzt wird. TOIE0 ist in der avr-libc für den atmega8 
z.B. so definiert:
1
#define TOIE0   0

Also ist
1
1 << TOIE0;
genau das gleiche wie:
1
1 << 0;

Man könnte auch
1
12 << TOIE0;
schreiben, auch wenn das in dem Fall keinen Sinn ergeben würde. Dann 
würde eben eine 12 um TOIE0 bits nach links geschoben statt einer 1.
OP #3136447
>Die "Bitnamen" sind auch nichts weiter als Präprozessor-Makros...

Danke nochmals, das sollte eventuell im Artikel "Bitmanipulation" 
erwähnt werden... Doch das überlasse ich lieber anderen, es ist zu 
wahrscheinlich, das ich irgend etwas Falsches rein schreibe...

>Denk mal darüber nach, warum man sich sehr viel Arbeit gemacht hat, um
>dort einen Einstieg in die C-Programmierung zu geben.

Och komm schon, wenn das dort ausführlich erklärt wäre, würde ich nicht 
fragen... Ich habe durchaus einige Zeit verbracht, um die Antwort 
alleine zu finden, habe es aber nicht geschafft, da die Erklärung dazu 
über drei Artikel verteilt ist(Bitmanipulation, AVR-GCC-Tutorial/Die 
Timer und Zähler des AVR, AVR-GCC-Tutorial). Wenn man schon weiß wie es 
geht, dann versteht man die Erklärung auch, aber für einen, der es 
gerade lernen will, ist das kaum möglich. Ich will nicht sagen, dass die 
Personen, die diese Artikel geschrieben haben, schlechte Arbeit 
geleistet haben(ganz im Gegenteil, sie haben freiwillig und ohne Lohn zu 
verlangen ein riesiges Projekt auf die Beine gestellt, Respekt!), aber 
als Eingeweihter kann man einfach nicht an alles denken, was ein Neuling 
falsch verstehen könnte.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 13 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.