PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : EXT_INT1



AsuroNeu
28.07.2009, 16:26
In Asuro wird ja der EXT_INT1 um den Taster Zustand zu bestimmen benutzt.
Wenn eine Taste gedrückt wird, ist die Variable 'switched' = 1. Diese Variable muss selber wieder im Software züruckgesetzt werden.

Um diesen Interrupt zu Aktivieren/Deaktivieren haben wir zwei Methoden, nämlich StartSwitch() und StopSwitch(), definiert. Die Methoden dienen nur um diesen Interrupt zu zulassen/sperren.

Muss dieser Interrupt gesperrt werden? Was ist wenn dieser Interrupt von Anfang an zugelassen bleibt? Gibt es da andere Probleme?

Bitte, mir hier weiterhelfen. Danke.

Bääääär
10.08.2009, 15:56
Hi AsuroNeu!

Der Interrupt ist nicht von Anfang an aktiviert. Das geschieht erst mit StartSwitch(); Du musst nix machen,w enn du ihn nicht brauchst.

Außerdem, selbst wenn er angeschaltet wäre, wen juckt's? Dann ist eben switched beim ersten Tastendruck 1 und danach kommt kein Interrupt mehr, weil der sich mit dem Eintreten (soweit ich weiß) selbst deaktiviert. Wenn du die Variable switched nie anschaust, kann dir das ja dann egal sein.

Bääääär

AsuroNeu
10.08.2009, 17:47
Erstmal danke für die Antwort.

Ich habe es gesehen, dass dieser Interrupt nicht von Anfang an aktiviert ist. Wenn man StartSwitch() aufruft wird er aktiviert und beim Aufrufen der Methode StopSwitch() wird er deaktiviert. Die variable switched wird in der ISR für dieser Interrupt gesetzt. Der programmierer muss dieser Variable selber wieder zürucksetzen ansonsten hat dieser variable den Wert 1 nachdem er einmal gesetzt wird.
Meine Frage war, was passiert wenn wir einfach diesen Interuppt in der Init Methode einmal aktivieren und ihn so lassen? Die variable switched wird nachwie vor in der ISR gesetzt und der programmierer muss ihn selber wieder zürucksetzen. Gäbe es da andere Probleme?

Vielen Dank im voraus.

Bääääär
10.08.2009, 18:21
Hallo mal wieder!

Achso war das gemeint. Soweit ich den Code überblickt habe, deaktiviert sich der Interrupt von selbst, nachdem er einmal ausgelöst wurde.

00248 SIGNAL (SIG_INTERRUPT1)
00249 {
00250 switched = 1;
00251 GICR &= ~(1 << INT1); // Externen Interrupt 1 sperren
00252 // StopSwitch ();
00253 }

das steht hier (http://www.asurowiki.de/pmwiki/pub/html/asuro_8c-source.html). Das deaktivieren passiert in Zeile 251. Demnach tritt ein erneuter Interrupt beim Tastendruck nur dann ein, wenn man ihn per StartSwitch() wieder aktiviert.
Für das Programm muss man für jede Interrupt-Abfrage, die man machen will, die Variable switched wieder zurücksetzen und StartSwitch() aufrufen. Macht man das nicht, passiert nichts.

Nur das zurücksetzen der switched-Variable per switched = 0; oder dergleichenaktiviert den Interrupt nicht wieder.

Ich hoffe, das war, was du meintest =)

Bääääär

AsuroNeu
10.08.2009, 18:54
Schon in die Richtung.

Warum müssen wir diesen Interrupt sperren? Warum können wir nicht, das was in StartSwitch() steht, einfach in die Init() Methode reinschreiben und diesen Interrupt immer zulassen?


void StartSwitch()
{
SWITCH_OFF; // Port-Bit auf LOW
DDRD &= ~SWITCHES; // Port-Bit SWITCHES als INPUT
MCUCR &= ~(_BV(ISC11) | _BV(ISC10)); // Low level erzeugt Interrupt
GICR |= _BV(INT1); // Externen Interrupt 1 zulassen
}


Ein mögliches Problem ist das PollSwitch() nicht mehr richtig funtioniert.


unsigned char PollSwitch (void)
{
unsigned int i;
int ec_bak = autoencode; // Sichert aktuellen Zustand

/*
Autoencode-Betrieb vom ADC-Wandler unterbinden.
*/
autoencode = FALSE;

DDRD |= SWITCHES; // Port-Bit SWITCHES als Output
SWITCH_ON; // Port-Bit auf HIGH zur Messung
i = ReadADC(SWITCH, 10);

SWITCH_OFF; // Port-Bit auf LOW
Sleep (5);

/*
Autoencode-Betrieb vom ADC-Wandler wiederherstellen.
*/
autoencode = ec_bak;

/*
Die Original Umrechenfunktion von Jan Grewe - DLR wurder ersetzt durch
eine Rechnung ohne FLOAT-Berechnungen.
return ((unsigned char) ((( 1024.0/(float)i - 1.0)) * 61.0 + 0.5));

Wert 61L evtl. anpasssen, falls fuer K1 falsche Werte zurueckgegebn werden.
*/
return ((10240000L / (long)i - 10000L) * MY_SWITCH_VALUE + 5000L) / 10000;
}


Für PollSwitch() muss PORT D als Ausgang und die Tasten Sensoren an (siehe Code) gesetzt werden. Aber für den Interrupt ist das genau anders rum.

Die PollSwitch() Methode kann so geschrieben werden.



unsigned char PollSwitch (void)
{
unsigned int i;
int ec_bak = autoencode; // Sichert aktuellen Zustand

/*
Autoencode-Betrieb vom ADC-Wandler unterbinden.
*/
autoencode = FALSE;

DDRD |= SWITCHES; // Port-Bit SWITCHES als Output
SWITCH_ON; // Port-Bit auf HIGH zur Messung
i = ReadADC(SWITCH, 10);

SWITCH_OFF; // Port-Bit auf LOW
DDRD &= ~SWITCHES; // Port-Bit SWITCHES als INPUT
Sleep (5);

/*
Autoencode-Betrieb vom ADC-Wandler wiederherstellen.
*/
autoencode = ec_bak;

/*
Die Original Umrechenfunktion von Jan Grewe - DLR wurder ersetzt durch
eine Rechnung ohne FLOAT-Berechnungen.
return ((unsigned char) ((( 1024.0/(float)i - 1.0)) * 61.0 + 0.5));

Wert 61L evtl. anpasssen, falls fuer K1 falsche Werte zurueckgegebn werden.
*/
return ((10240000L / (long)i - 10000L) * MY_SWITCH_VALUE + 5000L) / 10000;
}


Die ISR für diesen Interrupt wird dann so aussehen.


SIGNAL (SIG_INTERRUPT1)
{
switched = 1;
}

Also nur die Variable switched setzen. Das Rücksetzen dieser Variable ist nach wie vor den Programmierer überlassen.

Mit diesen geänderten Funktionen muss doch alles wie früher funktionieren oder? Kann es dadurch Probleme geben, dass wir diesen external Interrupt 1 immer zulassen statt nur wenn wir ihn brauchen?

AsuroNeu

Bääääär
10.08.2009, 19:15
Aha, so langsam kommen die Infos zusammen. Darum gehts also =)

Naja, sagen wir mal so: Warum muss ein Interrupt stattfinden, wenn wir das in dem Moment gar nicht brauchen? Wenn der Interrupt standardmäßig aktiviert ist, er aber nicht gebraucht wird, dann könnte er beispielsweise Lowlevel-Operationen unterbrechen, wenn diese nicht durch cli() und sei() geschützt sind. Im Prinzip geht es sicher, dass der Interrupt von Anfang an aktiv ist, unabhängig davon, ob er nun gebraucht wird oder nicht.

Es ist dann eben nur mehr Vorsicht geboten bei Operationen, die nicht durch einen Interrupt unterbrochen werden dürfen. Und da sich der ASURO maßgeblich an Einsteiger richtet, ist es sinnvoller, wenn diese Vorsicht gar nicht erst nötig ist. Von daher ist es in der Lib ganz gut so.

Aber Achtung: Ich experimentiere auch grade damit rum und versuche die Messung der Taster innerhalb der ISR zu machen. Allerdings wird dabei der Interrupt-pin auf Low gezogen und dadurch wird ein weiterer Interrupt ausgelöst, der nach abschluss der ISR aufgerufen wird und dann wieder einen Interrupt auslöst.
Soll Heißen, dass jede Messung, während die ISR aktiv ist, nach dieser Art und Weise jeweils einen Interrupt triggern würde obwohl gar kein Taster gedrückt wurde. Von daher würde ich das doch lieber manuell reaktivieren.
Oder eben bei der PollSwitch() am Beginn den Interrupt deaktivieren und am Ende wieder Einschalten. So hab ich's versucht, aber es geht nicht. Siehe dazu hier (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=455152)

Bääääär

AsuroNeu
11.08.2009, 10:49
Die PollSwitch() hat ja einen kleinen Fehler in der Funktion gehabt. Hast du das in deinem Code geändert?

Die PollSwitch() Methode sieht nämlich so aus.


DDRD |= SWITCHES; // Port-Bit SWITCHES als Output
SWITCH_ON; // Port-Bit auf HIGH zur Messung
i = ReadADC(SWITCH, 10);

DDRD &= ~SWITCHES; // Port-Bit SWITCHES als Input
SWITCH_OFF;


Nach der Messung muss der PortD wieder auf Eingang geschaltet werden. Diese Zeile fehlte. Siehe https://www.roboternetz.de/phpBB2/viewtopic.php?t=17240