PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : externer INT1 Mega8



hacker
03.10.2010, 17:26
Hallo zusammen,

ich habe folgenden Code:


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

#include <gue.h>
#include <adc.h>

short currentValue = 0;
unsigned char condition = 0;
short threshold = 0;

void init_gue(void)
{
// Grenzüberwachung Timer
TCCR2 |= (1 << WGM21) | (1 << CS01) | (1 << CS00);
//OCR2 = 250 ergibt 1kHz
OCR2 = 250; // ergibt 10kHz
// HW Interrupt Erkennungspin als Eingang definieren
DDRD &= ~(1 << DDD3);
// INT1 steigende Flanke
MCUCR |= (1 << ISC11) | (1 << ISC10);
// Ausgang für Meldung an die Sollsignalgenerierung
DDRC |= (1 << DDC5);
// anschalten, da Perioden Stop low aktiv ist
PORTC |= (1 << PC5);
// SW Notauspin auf Ausgang
DDRD |= (1 << DDD7);
// kein Notaus durchführen
PORTD &= ~(1 << PD7);
}

void gue_setCondition(unsigned char above)
{
condition = above;
}

void gue_setValue(unsigned short value)
{
threshold = (short)value;

// Threshold Wert ebenfalls transformieren, weil im gleichen Werteraum wie ADC gesendet wird.
if (threshold >= 2048)
{
threshold -= 4096;
}
}

void gue_start(void)
{
// "Berichterstattung" für Signal generierung zurücksetzten
PORTC |= (1 << PC5);
// condition == 2 soll der SW GÜ ausgeschaltet sein.
if ((condition == 0) | (condition == 1)){
// Grenzüberwachung starten
TIMSK |= (1 << OCIE2);
}

// INT1 enablen für HW Notaus Erkennung
GICR |= (1 << INT1);
}


void gue_stop(void)
{
// Grenzüberwachung stoppen
TIMSK &= ~(1 << OCIE2);
// INT1 disablen
GICR &= ~(1 << INT1);
}

void gue_stop_signal(void)
{
// fallende Flanke erzeugen
PORTC &= ~(1 << PC5);
}

void gue_do_emergency_stop(void)
{
// Notaus erzeugen
PORTD |= (1 << PD7);
}


ISR(TIMER2_COMP_vect)
{
// mit 10kHz Abtastrate schauen, ob man ein Notaus durchführen soll

// aktuellen Wert, der für die zusätzliche Software Grenzüberwachung heran gezogen wird, messen
//currentValue = (short)adc_read();

// ADC Wert transformieren
/*if (currentValue >= 2048)
{
currentValue -= 4096;
}*/
// Condition = 1 -> wenn istwert GRÖßER als die Schranke
// Condition = 0 -> wenn istwert KLEINER als die Schranke
/*if ((condition == 1) & (currentValue > threshold))
{
gue_do_emergency_stop();
}
if ((condition == 0) & (currentValue < threshold))
{
gue_do_emergency_stop();
}*/


}

ISR(INT1_vect)
{
// HW Notaus wurde erkannt --> Sollsignal stoppen!
gue_stop_signal();
gue_stop();
// SW Notaus wieder zurück setzten
PORTD &= ~(1 << PD7);
}


...und folgendes Problem:

Während der Initialisierung wird eben auch die Funktion init_gue() aufgerufen. Diese setzt den PC5 auf High Pegel.
So jetzt kommt von UART ein Trigger, der das Ganze starten lässt bzw. die Funktion gue_start() aufruft.

Nun mess ich an dem Pin und ich hab nur noch 0V anliegen. Die einzige Möglichkeit, welchen diesen Pin zurücksetzt, führt über die ISR zum INT1. Nach der Initialisierung ist der Pin auf +5V; das hab ich überprüft.

So jetzt ist mein Verdacht, dass sich der Controller obwohl der INT1 noch nicht eingeschaltet ist, trotzdem die Interrupts registriert und im GIFR Register kenntlich macht. Aber eben keine ISR aufgerufen wird.
Sobald ich nun den INT1 aktiviere, wird sofort ein Interrupts ausgelöst und in die ISR gesprungen.

Kann das sein?

Ich werde morgen mal probieren, vor dem Aktivieren des Interrupts das entsprechende Flag im GIFR zu löschen. Vielleicht hilft das.

Aber untergekommen ist mir das noch nie. Ich hatte eigentlich damit noch nie Probleme.

Sollte man somit generell vor dem Aktivieren der Interrupts die entsprechenden Flags löschen?


Grüße,
hacker

Jaecko
03.10.2010, 19:06
Das ist so. Wenn eine (konfigurierte) Interruptbedingung vorliegt, wird das entsprechende Flag gesetzt. Erst wenn die Interrupts dann freigegeben werden, wird die jeweilige ISR auch angesprungen. Ist sozusagen ein "Nebeneffekt" der Funktion, dass ankommende Interrupts nicht "vergessen" werden, wenn der Controller selbst gerade eine ISR ausführt.

Das Löschen der Flags vor dem Aktivieren ist bei mir eigentlich schon gewohnheitsmässig drin. Ob mans braucht oder nicht, hängt davon ab, obs Probleme machen könnte.

hacker
08.10.2010, 13:27
Danke. Hat jetzt auch wunderbar funktioniert, so wie es sein sollte.

Ich werde ab jetzt wohl auch vor jeder Aktivierung eines Interrupts die Flags löschen.