Hallo,
ist das wirklich dein ganzer Source Code? Denke nicht, so würde das ja nicht mal kompilieren. . .
Das if ist denke ich in ner Endlosschleife drin, oder?
und warum hast du sachen die zeittick=0 auskommentiert?
lg MoFe
Hai,
ich hab ein Problem mit einer Interrupt-Routine. Ich habe folgenden Code (Ausschnit).
Die ISR "TIM1_OVF_vect" wird angesprungen, der Timer läuft, alles prima. Aber die If-Abfrage im Hauptprogramm wird einfach nich ausgeführt. Stecke ich diese Abfrage in die ISR gehts. Wo hab ich da einen Fehler drin ? Wie kann ich eine Variable in einer ISR sonst manipulieren und im Hauptprogramm abfragen ?Code:#include <../include/avr/io.h> #include <../include/avr/interrupt.h> #include <../include/stdlib.h> #include <../include/util/delay.h> volatile uint16_t Zeittick = 0 ; SIGNAL (TIM1_OVF_vect) { // ISR-Code //PORTB ^= (1<<PB2); PORTB |= (1 << PB2); /* setzt Bit 3 an PortB auf 1 */ //PORTB &= ~(1 << PB2); /* loescht Bit 3 an PortB */ Zeittick++; } int main (void) { //Zeittick = 0; if (Zeittick >= 20) { //PORTB ^= (1<<PB3); //Zeittick = 0; PORTB |= (1 << PB3); // setzt Bit 3 an PortB auf 1 }
Ist die If-Agbfrage in der ISR taucht das Problem auf, dass die Variable Zeittick bei einem Softreset nicht zuverlässig auf Null gesetzt wird. ICh versteh aber nicht warum....
Internette Grüße
Stefan
Hallo,
ist das wirklich dein ganzer Source Code? Denke nicht, so würde das ja nicht mal kompilieren. . .
Das if ist denke ich in ner Endlosschleife drin, oder?
und warum hast du sachen die zeittick=0 auskommentiert?
lg MoFe
Hallo Moritz,
natürlich ist das nicht mein ganzer Code. Es ist nur der interessante Ausschnitt. Vom Rest weiß ich, dass es läuft. Du hast recht hinter der If-Abfrage kommt noch eine Endlosschleife. Mir geht es auch nur darum erst mal zu sehen, dass die entsprechende LED (PB3) überhaupt reagiert wenn die if-Abfrage im Hauptprogramm ist. Die auskommentierten Stellen sollen ein wenig zeigen, was ich schon versucht hab. Das Programm macht so, wie es da steht keinen Sinn, da geb ich dir Recht. Das Problem mit der globalen Variable kann man aber denke ich nachvollziehen. Bei Interesse poste ich auch den gesamten Code, der ist aber denke ich erstmal unwichtig.
Internette Grüße
Stefan
Mit 16bit / 2 byte Variablen ist das so eine Sache zwischen ISR und Main.
Ich persönlich mache meist solche "if"s in der ISR und setze nur einen Flag für die Mainroutine
Eigentlich aber seh ich keinen Fehler. Versuch wirklich einfach mal ein uint8_t , also nur ein Byte
mfg robert
Wer glaubt zu wissen, muß wissen, er glaubt.
Wenn die Endlosschleife nach der if-Schleife beginnt, kann sie ja nicht angesprungen werden.Du hast recht hinter der If-Abfrage kommt noch eine Endlosschleife.
Hallo an alle,
danke für eure prompten Antworten. Leider bin ich immer noch nicht weiter. Die If-Abfrage muss natürlich in die Endlosschleife. Ich hatte vorher da stehen Zeittick = 0 und in der if-Abfrage if Zeittick == 1
Habe die Abfrage jetzt wieder in die Endlosschleife genommen, aber ohen Erfolg. Auch die Verwendung einer unit8_t Variable brachte keinen Unterschied
Ich poste mal den gesamten Code, vielleicht hab ich ja doch anderer Stelle einen Denkfehler.....
Ich verstehs nicht. Wenn noch jemand eine Idee hat wäre das klasse. Nur noch als Info, mit diesem Code könnt ihr alle vier PWM Kanäle des Tiny25 nutzen, klappt prima. Nur eben bis auf die Geschichte mit der globalen Variable.Code:#include <../include/avr/io.h> #include <../include/avr/interrupt.h> #include <../include/stdlib.h> #include <../include/util/delay.h> #define UPPPER_BOUND 10 volatile uint8_t Zeittick ; int myRand( int UpperBound ) { int x; while( (x = rand()) >= RAND_MAX - (RAND_MAX % UPPPER_BOUND) ) ; return x % UPPPER_BOUND; } // Eine nichtunterbrechbare Interrupt-Service-Routine SIGNAL (TIM1_COMPA_vect) { // ISR-Code //PORTB ^= (1<<PB2); //PORTB |= (1 << PB2); // setzt Bit 3 an PortB auf 1 PORTB &= ~(1 << PB2); // loescht Bit 3 an PortB Zeittick = Zeittick + 1; } SIGNAL (TIM1_OVF_vect) { // ISR-Code //PORTB ^= (1<<PB2); PORTB |= (1 << PB2); /* setzt Bit 3 an PortB auf 1 */ //PORTB &= ~(1 << PB2); /* loescht Bit 3 an PortB */ Zeittick = Zeittick + 1; } void long_delay(uint16_t ms) { for(uint16_t temp=0; temp<=ms; temp++){ _delay_ms(1);} } int main (void) { //Zeittick = 0; // allgemein GTCCR = 0b11100001; // Timer anhalten SREG |= (1 << 7); GIMSK = 0b00100000; PCMSK = 0b00000100; // Timer 0 TCCR0A = 0b11100001; // Timer0 A und B auf Phasecorrect PWM-Mode // und löschen bei erreichen des Werte in OC0A bzw. // OC0B TCCR0B = 0b00000010; // WGM02-Bit löschen für PWM-POhase-Correct-Mode // OC0A-Ausgang wird beim hchzählen gesetzt und // beim runterzählen gelöscht // und Prescaler auf clk/1024 einstellen OCR0A = 0b01100011; // Output-Compare-Register einstellen OCR0B = 0b00101111; // Output-Compare-Register einstellen // Timer 1 TCCR1 = 0b01000101; OCR1A = 0b11000000; OCR1B = 0b00011111; OCR1C = 0b11111111; TIMSK = 0b01000100; // sei(); // OCR1A = 0b01111111; // OCR1B = 0b00111111; DDRB = 0b11111111; // PortB auf Ausgabe stellen GTCCR = GTCCR & 0b11111110 ;//0b00000000; // Timer starten uint8_t Dauer_LED1 = 2;//myRand(255); uint8_t Helligkeit_LED1 = 255;//myRand(255); uint8_t LED1; while(1) { if (Zeittick >= 3) { //PORTB ^= (1<<PB3); //Zeittick = 0; PORTB |= (1 << PB3); // setzt Bit 3 an PortB auf 1 } /* for (LED1 = 0; LED1<Helligkeit_LED1;LED1++) { OCR1B=LED1; _delay_ms(Dauer_LED1); } //PORTB |= (1 << PB2); // setzt Bit 3 an PortB auf 1 //long_delay(1000); for (LED1 = 0; (Helligkeit_LED1-LED1)>0;LED1++) { OCR1B=255-LED1; _delay_ms(Dauer_LED1); } */ //PORTB &= ~(1 << PB2); // loescht Bit 3 an PortB //long_delay(1000); /* OCR0A = 100; long_delay(1000); // Eine Sekunde warten... OCR0A = 1; long_delay(1000); // Eine Sekunde warten... */ //PORTB |= (1 << PB2); /* setzt Bit 3 an PortB auf 1 */ } return 0; }
Internette Grüße
Stefan
Hallo,
deine Schreibweise finde ich immer noch nicht schön. Aber das muss ich ja auch nicht. Einige Zeilen sind aber ganz ansehnlich und da fällt mir auf den ersten Blick auf:
in der ISR
PORTB &= ~(1 << PB2); // loescht Bit 3 an PortB
in main
PORTB |= (1 << PB3); // setzt Bit 3 an PortB auf 1
Da passt doch was nicht.
Einen Reset mit Software löst du am besten über den Watchdog aus oder du ziehst über einen Pin den Reset auf 0. Dann wird auch auch alles richtig initialisiert.
Gruß
Jens
Hallo Jens,
hast recht, die Kommentare stimmen nicht ganz, was vor den // steht zählt, in sofern ist das schon korrekt. Ändert aber auch nichts an dem Problem der Variablenübergabe von ISR zu Main mittels globaler Variable. Das mit dem Reset hat mich auch verwundert. Ich nutze ein STK500 zum entwickeln. Wenn ich dort die Reset-Taste drücke, wird die Variable Zeittick anscheinend nicht initialisiert. Durch die Reset-Taste bin ich ja erst auf die Sache überhaupt aufmerksam geworden.
Internette Grüße
Stefan
Ist die Groß-Kleinschreibung sicher korrekt ?
TIM1_OVF_vect
(GCC macht sich da ins Halstuch)
mfg robert
Wer glaubt zu wissen, muß wissen, er glaubt.
Hai,
die Schreibweise ist korrekt, ich hab sie direkt aus dem Header-File kopiert und die ISR werden ja auch angesprungen.
Internette Grüße
Stefan
Lesezeichen