mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega8 - IF-Schleife wird ignoriert


Autor: Nico H. (gecko2152)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
Seit einiger Zeit beschäfftige ich mich jetzt schon mit µControllern 
aber jetzt steh ich vor einem Problem, wo ich einfach nicht weiter weiß.

Ich habe unter AVR ein Beispiel Code geschrieben und simuliert um zu 
schauen ob es funktioniert: hier mal ein auszug.

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/iom8.h>

uint8_t zaehler0=0,start=0,status=0,status1=0,zahl=0;

int main(void)
{
  DDRD |=  (1<<PD7);

  //Timer0 starten
  TCCR0 |= (1<<CS02)|(1<<CS00);  //Vorteiler gleich 1024 (Timer0)
  TIMSK |= (1<<TOIE0);      //Interrupt an --> kommt alle 65,5 ms

  sei();    //Interrupts ein

  while(1)
  {
      //Zählschleife
      if (zaehler0>=4)   //wenn der Zähler mind 4 mal einen Overflow
      {          //erzeugt (250ms) hat soll diese Schleife ausgeführt 
werden
        //Testfkt --> LED an und aus
        if (start==1)
        {
          PORTD |= (1<<PD7);
          start=0;
        }
        else
        {
          PORTD &=~ (1<<PD7);
          start=1;
        }
        zahl=0;//Rücksetzen des Zählers
      }
  }

return(0);
}

ISR(TIMER0_OVF_vect)  //Interrupt Timer0 alle 65.5 ms
{
  zahl++;
  //if (zahl>=4)
  //{ zahl=0;}
}

Und jetzt kommt der Knackpunkt
Die Zahl wird brav hochgezählt doch in der While-Schleife springt das 
Programm nie in die If-Anweisung obwohl die Variable schon längst 4 oder 
größer erreicht hat.

Bei einem anderen Projekt mit einem Atmega32 hab ich den selben 
Programmcode verwendet um eine Led zum blinken zu bringen und dort hat 
es wunderbar funktioniert und nun nicht mehr.

Kennt einer dieses Problem oder eine Ahnung woran es liegen kann?

Ich hab auch schon ausbrobiert unabhängig vom Timer einfach in der while 
schleife ne variable hochzählen zu lassen, aber selbst das macht er 
nicht.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nico H. schrieb:

> Die Zahl wird brav hochgezählt doch in der While-Schleife springt das
> Programm nie in die If-Anweisung obwohl die Variable schon längst 4 oder
> größer erreicht hat.

Kann ich mir nicht vorstellen.
Du zählst die Variable 'zahl' hoch.
Abfragen tust du aber die Variable 'zaehler0'

PS: zahl musst du als volatile definieren.
volatile uint8_t zahl;

> Bei einem anderen Projekt mit einem Atmega32 hab ich den selben
> Programmcode verwendet um eine Led zum blinken zu bringen und dort hat
> es wunderbar funktioniert und nun nicht mehr.

Das ist die Krux, wenn man einfach Code von einem Projekt in ein anderes 
umkopiert: Du musst dir immer ansehen, welche Variablen wie verwendet 
werden und ob das alles zusammenpasst.
Ganz einfach nur die Variablen nachdefinieren, die der Compiler 
anmeckert ist zuwenig.

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nico H. schrieb:

> Bei einem anderen Projekt mit einem Atmega32 hab ich den selben
> Programmcode verwendet um eine Led zum blinken zu bringen und dort hat
> es wunderbar funktioniert

unwahrscheinlich..du zählst zahl hoch und fragst zaehler0 ab...

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1.
Du erhöhst im Interrupt zahl, testest in der Schleife aber zaehler0.

2.
volatile

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun ja, in der ISR zahl++ zu schreiben, und dann auf if (zaehler0>=4) zu 
prüfen, ist irgendwie wenig sinnvoll.

Als nächstes fehlt dann da ein volatile.

Und
>#include <avr/iom8.h>
ist überflüssig.

Oliver

Autor: Nico H. (gecko2152)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ach ups das hatte ich noch nicht wieder geändert

hab da soviel rumgespielt das ich das wieder vergessen hab zurück zu 
ändern also der Code nochmal so wie er auch sein soll, aber trotzdem net 
funzt

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/iom8.h>

uint8_t zaehler0=0,start=0,status=0,status1=0,zahl=0;

int main(void)
{
  DDRD |=  (1<<PD7);

  //Timer0 starten
  TCCR0 |= (1<<CS02)|(1<<CS00);  //Vorteiler gleich 1024 (Timer0)
  TIMSK |= (1<<TOIE0);      //Interrupt an --> kommt alle 65,5 ms

  sei();    //Interrupts ein

  while(1)
  {
      //Zählschleife
      if (zaehler0>=4)   //wenn der Zähler mind 4 mal einen Overflow
      {          //erzeugt (250ms) hat soll diese Schleife ausgeführt
werden
        //Testfkt --> LED an und aus
        if (start==1)
        {
          PORTD |= (1<<PD7);
          start=0;
        }
        else
        {
          PORTD &=~ (1<<PD7);
          start=1;
        }
        zaehler0=0;//Rücksetzen des Zählers
      }
  }

return(0);
}

ISR(TIMER0_OVF_vect)  //Interrupt Timer0 alle 65.5 ms
{
  zaehler0++;
  //if (zahl>=4)
  //{ zahl=0;}
}


Nachtrag: Jetzt hab ich aber das mit dem volatile ausprobiert und auf 
einmal funzt es, aber wie kann es sein das ich hier volatile benutzen 
muß und ich damlas beim atmega32 das nicht braucht?

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
volatile fehlt immer noch und zurücksetzen solltest du auch zaehler0 und 
nicht zahl...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nico H. schrieb:

> Nachtrag: Jetzt hab ich aber das mit dem volatile ausprobiert und auf
> einmal funzt es, aber wie kann es sein das ich hier volatile benutzen
> muß und ich damlas beim atmega32 das nicht braucht?

Das kann daher kommen, das dein Programm am atmega32 damals anders 
ausgesehen hat und der Optimizer keine Chance hatte, die betreffénde 
Variable in einem CPU Register vorrätig zu halten, so dass er bei der 
nächsten Abfrage nicht erst den Wert langsam aus dem SRAM holen musste, 
sondern schnell aus einem Register holen konnte.

Denn genau das macht volatile: Es teilt dem Compiler mit, dass sich eine 
Variable auf Wegen ändern kann, die der Compiler naturbedingt bei einer 
Datenflussanalyse nicht erkennen kann und er daher auch tatsächlich auch 
immer auf die Variable zugreifen soll, wenn du in deinem Code einen 
Zugriff programmierst. Ist eine Variable nicht volatile, dann versucht 
der Compiler, Zugriffe aufs SRAM zu vermeiden, indem er zb davon 
ausgeht, dass sich eine Variable zwischen 2 Codestellen, zwischen denen 
die Variable seiner Meinung nach nicht verändert wird, in der CPU in 
einem Register vorrätig zu halten. Dumm nur, wenn eine ISR 
dazwischenhaut und die Variable im SRAM ändert, der Abfragecode aber 
nichts davon weiß und mit dem im CPU Register-Cache vorrätig gehaltenen 
Wert weiterrechnet.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
<Pedanterie>

Es gibt keine "if-Schleifen".

Schreib' das jetzt mindestens sooft, wie Deine "if-Schleife" nicht 
durchlaufen wird.

</Pedanterie>

Autor: Nico H. (gecko2152)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tschuldige meinte natürlich if-anweisung

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.