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.
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.
1 | 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.
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...
1. Du erhöhst im Interrupt zahl, testest in der Schleife aber zaehler0. 2. volatile
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
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?
volatile fehlt immer noch und zurücksetzen solltest du auch zaehler0 und nicht zahl...
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.
<Pedanterie> Es gibt keine "if-Schleifen". Schreib' das jetzt mindestens sooft, wie Deine "if-Schleife" nicht durchlaufen wird. </Pedanterie>
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.