led toogle mit mega88

Gast #811053
Hallo,

folgendes Programm mit einem ATmega88 läuft bei mir nicht:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3

4
#define F_CPU 8000000
5

6
volatile int counter = 0;
7

8

9
int main( void ) {
10

11
  DDRC = 0xFF;                    // PORTC als Ausgang, LEDS aus
12

13
  TCCR0B |= (1<<CS00) | (1<<CS02);          // Prescaler = 1024, Timer aktivieren
14
  TIMSK0 |= (1<<TOIE0);                // Interrupt für TimerOverflow aktivieren
15
  sei();                        // Interrupts global aktivieren
16

17
  PORTC = 0x00;                    // Alle LEDS an
18

19
  return(0);    
20
}
21

22

23
ISR( TIMER0_OVF_vect ) {                // Timer InterruptHandler, Ausführung 30.5 mal pro Sekunden
24
  
25
  counter++;  
26
    
27
  if( counter >= 5 ) {
28

29
    switch( PORTC ) {
30

31
    case 0x00:
32
      
33
      PORTC = 0xFF;
34

35
    case 0xFF:
36

37
      PORTC = 0x00;
38

39
    }
40
  
41
  counter = 0;
42

43
  }  
44
}


Ich habs jetzt schon so oft kontrolliert aber ich find den Fehler nicht. 
Die Leds bleiben einfach an, da tut sich nichts. Sollten eigentlich so 
ca. 6 mal pro Sekunde wechseln. Das CKDIV8 Fuse ist nicht gesetzt.

Thx
Gast
Hi,

Dein main() läuft 1x bis zum "return" und dann? Also

int main(void){

// Initialisierung etc.
   sei;

   while (1) {};

   return 1; // nur um den Compiler glücklich zu machen....
}

Gruß

Fred
An die Drei "while(1)"-Poster:

Das brauchts nicht wirklich, diese Enlosschleife ist in der avr-libc 
(Startupcode) mit drinnen, falls man wirklich aus der main returned:
1
00000054 <main>:
2
......
3
  60:   00 c0           rjmp    .+0             ; 0x62 <_exit>
4

5
00000062 <_exit>:
6
  62:   ff cf           rjmp    .-2             ; 0x62 <_exit>
1
switch( PORTC ) {
2

3
    case 0x00:
4
      
5
      PORTC = 0xFF;
6

7
    case 0xFF:
8

9
      PORTC = 0x00;
10

11
    }
Das ganze ist ziemlich umständlich. Schreib lieber
1
PORTC ~= PORTC;
oder
1
PORTC ^= 0xFF;
Das ist ein bisschen kürzer und macht im Prinzip dasselbe...
Gast
Hallo Ernst,

> Das brauchts nicht wirklich, diese Enlosschleife ist in der avr-libc
> (Startupcode) mit drinnen, falls man wirklich aus der main returned:
...danke, das hatte ich nicht gewusst!

Gruß

Fred
Gast
da tut sich aber auch nichts wenn ich den counter zb auf 100 erhöhe, 
habs jetzt mal mit PortD versucht:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3

4
#define F_CPU 8000000
5

6
volatile int counter = 0;
7

8

9
int main( void ) {
10

11
  DDRD = 0xFF;                    // PORTC als Ausgang, LEDS aus
12

13
  TCCR0B |= (1<<CS00) | (1<<CS02);          // Prescaler = 1024, Timer aktivieren
14
  TIMSK0 |= (1<<TOIE0);                // Interrupt für TimerOverflow aktivieren
15
  sei();                        // Interrupts global aktivieren
16

17
  PORTD = 0x00;                    // Alle LEDS an
18

19
  while( 1 )
20

21
  return(0);    
22
}
23

24

25
ISR( TIMER0_OVF_vect ) {                // Timer InterruptHandler, Ausführung 30.5 mal pro Sekunden
26
  
27
  counter++;  
28
    
29
  if( counter >= 100 ) {
30

31
    switch( PORTD ) {
32

33
    case 0x00:
34
      
35
      PORTD = 0xFF;
36

37
    case 0xFF:
38

39
      PORTD = 0x00;
40

41
    }
42
  
43
  counter = 0;
44

45
  }  
46
}
Es ist auch nicht sinnvoll, für eine Zählvariable einen 16-Bit-Integer 
zu nehmen, der dazu noch vorzeichenbehaftet ist. Mach aus der Variable 
mal
1
volatile unsigned char counter;
Die Initialisierung mit 0 kann man sich bei globalen Variablen sparen.
1
 while( 1 )
2

3
  return(0);
Das ist auch Unsinn. Hinter dem while(1) fehlt ein Semikolon. Das return 
kann man sich dann komplett schenken. Abgesehen davon gehören keine 
Klammern um das "Argument" von return. Wenn schon, dann
1
while(1);
2

3
return 0;
Hallo Gast!
Du hast die Initialiesierungen alle man in der Main-Funktion drinne.
Die gehören davor, da diese eigentlich nur einmal aufgerufen werden 
sollen.
1
  DDRC = 0xFF;                    // PORTC als Ausgang, LEDS aus
2
  TCCR0B |= (1<<CS00) | (1<<CS02);      // Prescaler = 1024, Timer aktivieren
3
  TIMSK0 |= (1<<TOIE0);             // Interrupt für TimerOverflow aktivieren
4
  sei();                        // Interrupts global aktivieren
5
  PORTC = 0x00;                    // Alle LEDS an

Der ganze Kram muss VOR die Main-Funktion stehen.
Dann sollte es klappen ;-)
MFG K-Duke
Gast
Ok abgeändert, weiterhin leuchten die LEDs nur:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3

4
#define F_CPU 8000000
5

6
volatile unsigned char counter;
7

8

9
int main( void ) {
10

11
  DDRD = 0xFF;                    // PORTC als Ausgang, LEDS aus
12

13
  TCCR0B |= (1<<CS00) | (1<<CS02);          // Prescaler = 1024, Timer aktivieren
14
  TIMSK0 |= (1<<TOIE0);                // Interrupt für TimerOverflow aktivieren
15
  sei();                        // Interrupts global aktivieren
16

17
  PORTD = 0x00;                    // Alle LEDS an
18

19
  while( 1 );
20

21
}
22

23

24
ISR( TIMER0_OVF_vect ) {                // Timer InterruptHandler, Ausführung 30.5 mal pro Sekunden
25
  
26
  counter++;  
27
    
28
  if( counter >= 100 ) {
29

30
    switch( PORTD ) {
31

32
    case 0x00:
33
      
34
      PORTD = 0xFF;
35

36
    case 0xFF:
37

38
      PORTD = 0x00;
39

40
    }
41
  
42
  counter = 0;
43

44
  }  
45
}
Karsten B. wrote:
> Hallo Gast!
> Du hast die Initialiesierungen alle man in der Main-Funktion drinne.
> Die gehören davor, da diese eigentlich nur einmal aufgerufen werden
> sollen.
>
1
  DDRC = 0xFF;                    // PORTC als Ausgang, LEDS aus
2
>   TCCR0B |= (1<<CS00) | (1<<CS02);      // Prescaler = 1024, Timer
3
> aktivieren
4
>   TIMSK0 |= (1<<TOIE0);             // Interrupt für TimerOverflow
5
> aktivieren
6
>   sei();                        // Interrupts global aktivieren
7
>   PORTC = 0x00;                    // Alle LEDS an
>
> Der ganze Kram muss VOR die Main-Funktion stehen.
> Dann sollte es klappen ;-)
> MFG K-Duke
Vor der main()-Funktion dürfen überhaupt keine Initialisierungen 
stehen! Lies Dir mal ein C-Buch durch, bevor Du hier so einen Unfug 
erzählst! In C darf Code nur innerhalb von Funktionen stehen.

Der ganze Kram steht da schon richtig.
@ Gast:
Karlheinz hat natürlich völlig recht: solange immer noch das unsinnige 
und so wie es da steht nicht funktionierende switch-case da steht, 
kann es nicht funktionieren! Nimm eine der beiden von mir weiter oben 
geposteten Versionen. Die funktionieren sicher!

EDIT: Sehe grad, dass Du auf PORTD gewechselt hast. Sollte dann zwar 
eigentlich funktionieren, aber ist trotzdem unsinnig.
Gast
Wie du Recht hast :)

Mit:

PORTD ^= 0xFF;

funktionierts.

Mit:

PORTD ~= PORTD;

bekomm ich nen: ../LED_Strobo.c:34: error: expected ';' before '~' token


Warum funktioniert die Switch Anweisung so nicht?

Danke
Gast wrote:
> Mit:
>
> PORTD ~= PORTD;
>
> bekomm ich nen: ../LED_Strobo.c:34: error: expected ';' before '~' token
Das kann eigentlich nicht sein, wenn vorher alles stimmt. Ich vermute 
mal, Du hast in der Zeile davor einen Bock drin (eben z.B. ein 
vergessenes ";").
Siehst Du jetzt, warum switch an so einer Stelle völliger Unsinn ist? 
Erstens ist es fehleranfällig, zweitens macht switch nur dann Sinn, 
wenn man deutlich mehr als zwei Fälle unterscheiden muss und drittens 
gibt es grad in diesem Fall mehrere Varianten, das ganze einzeilig zu 
schreiben.

Wenn man schon eine Verzweigung mit zwei Möglichkeiten machen will, dann 
in so einem Fall ein if-else
1
if(!PORTD)
2
    PORTD = 0xFF;
3
else
4
    PORTD = 0;

Antwort schreiben

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