PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Externer Interrupt



Brands_Freund
24.02.2006, 20:55
Moinsen.

Hab mal ne kleine Frage bezüglich externen Interrupts.
Wollte meine Drehgeber auslesen und einen Zähler runter zählen lassen. Hab vorher schon meinen Bot mit nem IS741 stoppen lassen Programm (ähnlich und läuft). Für die Drehgeber habe ich das Programm modifiziert. Jetzt mein Problem: Programmbeginn - Der Roboter fährt los - Interrupt wird erkannt -Roboter hält an Warum? Die If Bedingung ist garnicht erfüllt. Oder doch? Counter schon runtergezählt? Kann das durch die Sinuscharteristik des Signals passieren? Funktioniert auch nicht wenn ich mit nem Taster ein besseres Signal eingebe. Oder habe ich einen kleine Fehler im Programm? Hier der Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

volatile uint8_t counter;


void initialise (Void)
{
DDRB = 0xFF;
DDRD = 0x00;
GIMSK |= (1<<INT0)|(1<<INT1);
MCUCR |= (0<<ISC01)|(0<<ISC00);
}

void warte (void)
{
warte();
}

SIGNAL (SIG_INTERRUPT0)
{
counter = counter - 1 ;
if (counter == 0)
{
PORTB = 0b11111111;
}
}

int main (void)
{
initialise();
counter == 10;
PORTB = 0b11110101;
sei();
warte();
}


Schonmal danke für mögliche Denkanstöße ](*,)

Cyclon
24.02.2006, 21:10
Liegts vielleicht am ==

counter == 10;

Du kannst, glaube ich auch das schreiben:

volatile uint8_t counter=10;

SprinterSB
24.02.2006, 22:04
(i) Es heisst void, nicht Void (sollte eigentlich nen Fehler geben)
(ii) warte() ruft sich selbst rekursiv auf, das schmiert ratze fatze ab!
(iii) count == 10; ist hier ohne Wirkung, dein Prog startet also mit count = 0. Der Rest steht bei Cyclon.
(iv) Port B wird immer auf 0xff bleiben, wenn es einmal dahin gesetzt wirde. Wenn das bisher anders war, dann deshalb, weil der Absturz (ii) möglicherweise einen Neustart ausgelöst hat.

Brands_Freund
25.02.2006, 10:40
Danke fürs void und fürs ==.
Aber das Problem ist immer noch das selbe. Hab auch die warte(); gegen ein while(1) in main getauscht und void warte (void) komplett rausgeschmissen.
Port B soll ja auch auf 0xff gesetzt werden wenn counter bei 0 ist.
Liegt es am while(1) die Varriante hab ich mal gesehen ob das so richtig ist hab ich noch nie probiert.
Wäre eine aufwärts Zählschleife besser?
Hier nochmal der Code:

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

volatile int counter=10;


void initialise (void)
{
DDRB = 0xFF;
DDRD = 0x00;
GIMSK |= (1<<INT0)|(1<<INT1);
MCUCR |= (0<<ISC01)|(0<<ISC00);
}

SIGNAL (SIG_INTERRUPT0)
{
counter = counter - 1 ;
if (counter == 0)
{
PORTB = 0b11111111;
}
}

int main (void)
{
initialise();
PORTB = 0b11110101;
sei();
while(1);
}




Dann noch ne allgemeine Frage: Warum hängen sich den rekursive Aufrufe wie meine warte() schnell auf? Oder nur in diesem speziellen Fall?

Danke nochmals

linux_80
25.02.2006, 12:22
Hallo,
schon mal überlegt was ist, wenn der Counter bei 0 angekommen ist, und in der nächsten runde nochmal 1 angezogen wird ?
zB. in der Abfrage ob der counter 0 ist, diesen gleich mit einem neuen Wert vorbelegen.

Warum sich das mit warte() aufhängt kommt daher, da es keine Abbruchbedingung gibt, und es im Prinzip ein Deadlock ist. Wenn warte() einmal aufgerufen wird kommt der nimmer da raus, pro funktionsaufruf wird eine Rücksprungadresse im Speicher hinterlegt, das geht solange gut bis der Speicher voll ist, dann schepperts.