www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik led toogle mit mega88


Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

folgendes Programm mit einem ATmega88 läuft bei mir nicht:

#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 8000000

volatile int counter = 0;


int main( void ) {

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

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

  PORTC = 0x00;                    // Alle LEDS an

  return(0);    
}


ISR( TIMER0_OVF_vect ) {                // Timer InterruptHandler, Ausführung 30.5 mal pro Sekunden
  
  counter++;  
    
  if( counter >= 5 ) {

    switch( PORTC ) {

    case 0x00:
      
      PORTC = 0xFF;

    case 0xFF:

      PORTC = 0x00;

    }
  
  counter = 0;

  }  
}


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

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Karlheinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PORTC = 0x00;                    // Alle LEDS an

 while ( 1 )
  ;

 return(0);
}

Autor: Philipp R. (relaxxo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
setz ne endlosschleife nach "PORTC = 0x00;"  in die main-routine. dann 
sollte es funktionieren.

Autor: Εrnst B✶ (ernst)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Im Anhang ein Schnipsel aus dem Datenbatt:
PORTC hat nur 7 Bits, dass höchstwertige (8te) Bit ist immer 0.

d.H. dein Vergleich PORTC==0xFF kann nie wahr werden.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da tut sich immer noch nichts. LEDs bleiben einfach an :-/

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aha, soll ichs dann so schreiben? 0b1111111 ? Oder per Bitmanipulation 
nur die Bits ansprechen, die ich wirklich brauche?

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
00000054 <main>:
......
  60:   00 c0           rjmp    .+0             ; 0x62 <_exit>

00000062 <_exit>:
  62:   ff cf           rjmp    .-2             ; 0x62 <_exit>

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
switch( PORTC ) {

    case 0x00:
      
      PORTC = 0xFF;

    case 0xFF:

      PORTC = 0x00;

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

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mich würd erstmal freuen wenn überhaupt was blinken würde ;) Aber 
trotzdem Danke

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
da tut sich aber auch nichts wenn ich den counter zb auf 100 erhöhe, 
habs jetzt mal mit PortD versucht:
#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 8000000

volatile int counter = 0;


int main( void ) {

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

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

  PORTD = 0x00;                    // Alle LEDS an

  while( 1 )

  return(0);    
}


ISR( TIMER0_OVF_vect ) {                // Timer InterruptHandler, Ausführung 30.5 mal pro Sekunden
  
  counter++;  
    
  if( counter >= 100 ) {

    switch( PORTD ) {

    case 0x00:
      
      PORTD = 0xFF;

    case 0xFF:

      PORTD = 0x00;

    }
  
  counter = 0;

  }  
}
    

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
volatile unsigned char counter;
Die Initialisierung mit 0 kann man sich bei globalen Variablen sparen.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
 while( 1 )

  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
while(1);

return 0;

Autor: Karsten B. (k-duke)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
  DDRC = 0xFF;                    // PORTC als Ausgang, LEDS aus
  TCCR0B |= (1<<CS00) | (1<<CS02);      // Prescaler = 1024, Timer aktivieren
  TIMSK0 |= (1<<TOIE0);             // Interrupt für TimerOverflow aktivieren
  sei();                        // Interrupts global aktivieren
  PORTC = 0x00;                    // Alle LEDS an

Der ganze Kram muss VOR die Main-Funktion stehen.
Dann sollte es klappen ;-)
MFG K-Duke

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok abgeändert, weiterhin leuchten die LEDs nur:
#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 8000000

volatile unsigned char counter;


int main( void ) {

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

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

  PORTD = 0x00;                    // Alle LEDS an

  while( 1 );

}


ISR( TIMER0_OVF_vect ) {                // Timer InterruptHandler, Ausführung 30.5 mal pro Sekunden
  
  counter++;  
    
  if( counter >= 100 ) {

    switch( PORTD ) {

    case 0x00:
      
      PORTD = 0xFF;

    case 0xFF:

      PORTD = 0x00;

    }
  
  counter = 0;

  }  
}

Autor: Karheinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Ernst: Danke auch von mir.

@Gast (Gast): Die switch Anweisung funktioniert nicht ( siehe Ernst 
Bachmann (ernst) und Johannes M. (johnny-m) )!

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
>
  DDRC = 0xFF;                    // PORTC als Ausgang, LEDS aus
>   TCCR0B |= (1<<CS00) | (1<<CS02);      // Prescaler = 1024, Timer
> aktivieren
>   TIMSK0 |= (1<<TOIE0);             // Interrupt für TimerOverflow
> aktivieren
>   sei();                        // Interrupts global aktivieren
>   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.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ 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.

Autor: Philipp R. (relaxxo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
switch( PORTD ) {

    case 0x00:
      PORTD = 0xFF;
    break;
    case 0xFF:
      PORTD = 0x00;
    break;
    }

muss die switch-anweisung nicht so aussehen?

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt ein break; hat gefehlt. So nimmt er das als eine 
Anweisung....verdammt

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast wrote:
> Warum funktioniert die Switch Anweisung so nicht?
Unter anderem, weil wir alle bis auf einen gewissen Relaxxo übersehen 
haben, dass Du die breaks vergessen hast! Zumindest nach dem ersten 
case muss ein break stehen!

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ";").

Autor: Philipp R. (relaxxo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ohne Break-anweisung werden die nachstehenden cases auch abgearbeitet. 
bis zum nächstem break bzw. zum Switch-Anweisungs-Ende

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
if(!PORTD)
    PORTD = 0xFF;
else
    PORTD = 0;

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar! Dank an alle. Schönen Abend noch.

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.