Forum: Mikrocontroller und Digitale Elektronik Verständnisproblem ISR am Attiny24


von Martin L. (martin_l795)


Lesenswert?

Hallo allerseits,

habe vor kurzem mit der AVR Programmierung angefangen und habe da grade 
ein Problem, das mich etwas verwirrt.
Kurze Beschreibung:
Attiny24A, simple Schaltung, Tastendruck an INT0 soll globale Variable 
setzen, main dann entsprechend handeln.
Klappt nur nicht.

Relevante Code-Teile sehen so aus:

/* GLOBALE VARIABLEN */
volatile uint8_t diceButtonPressed = 0; // Wuerfeltaste

/* INTERRUPT-ROUTINEN */
/* Bei Tastendruck Start des Wuerfelvorgangs. */
ISR(EXT_INT0_vect) {

  diceButtonPressed = 1;
  PINB |= (1<<TEST_OUT_PIN); // Test-LED Interrupt erreicht
  reti();
}

....
int main(void)
{
    uint8_t dicevalue = 0;

  initPorts();
  initInterrupts();

  while(1)
    {
    if (diceButtonPressed) {
    ...do a lot of strange and beautiful things...

...

So.... irgendwie wird aber die If-Bedingung nie erfüllt.
Die globale Variable, die als Marker dienen soll, ist als volatile 
gekennzeichnet.
Der Interrupt wird auch erreicht, d.h. der INT ist richtig enabled etc., 
Taste löst ihn auch aus, der ändert in der ISR den TEST_OUT_PIN, kann 
man sehr gut verfolgen. Die ISR müsste also die Variable auf 1 setzen 
und dann zurückkehren. Sehr simpel eigentlich.
Es gibt keinerlei andere Teile im Programm, die auf die 
diceButtonPressed Variable zugreifen, weder lesend noch schreibend.
Direkt hinter der if-bedingung hab ich auch schon die Ausgabe auf den 
Testpin vorgenommen, einfach um auszuschliessen, das da irgendwas nicht 
klappt, nix passiert. Der Teil hinter dem if wird einfach nie erreicht 
und ich kapiere nicht, warum nicht.

Wäre prima, wenn mir da jemand weiterhelfen könnte...

von (prx) A. K. (prx)


Lesenswert?

Interrupt einschalten: sei().

Was soll das reti() sein? Macht der Compiler selber und richtiger.

Aber: Taster als Quelle von Interrupt sorgt für Freude, weil er prellt.

: Bearbeitet durch User
von Martin L. (martin_l795)


Lesenswert?

Interrupt ist an. Wie geschrieben kommt er in die ISR.
Prellen ist in diesem Stadium noch egal und hat auf das Problem keine 
Auswirkungen.

von (prx) A. K. (prx)


Lesenswert?

Und das reti()?

von OldMan (Gast)


Lesenswert?

Martin Luerssen schrieb:
> PINB |= (1<<TEST_OUT_PIN); // Test-LED Interrupt erreicht

PINB wird Dir nicht wirklich etwas anzeigen.
Um ein Bit an einem Port zu setzen verwendet man PORT(X), in deinem Fall
PORTB. Dazu muss auch das DDRB Register richtig gesetzt sein.
PIN(X) wird zum einlesen verwendet.
Das mal als Hinweis.

Setzt Du die Variable diceButtonPressed in der main irgendwann auf 0?
Zeig mal den ganzen Code, sonst kann man Dir nicht wirklich helfen.

Und den reti() im ISR, schmeiß bitte raus.

von Martin L. (martin_l795)


Lesenswert?

Danke erstmal, Reti rausschmeissen versuche ich mal.
Natuerlich ist der Testpin auf Ausgang geschaltet und den mit 1 zu 
beschreiben invertiert den Zustand des Portausgangs. Ist die einfachste 
Art einen Portpin blinken zu lassen und so aucb in den Datasheets 
beschrieben.
Die diceButtonpressed Variable "würde" am ende des iif teils auf 0 
gesetzt. Wird aber ja nie erreicht.


VG
OldMan schrieb:
> Martin Luerssen schrieb:
> PINB |= (1<<TEST_OUT_PIN); // Test-LED Interrupt erreicht
>
> PINB wird Dir nicht wirklich etwas anzeigen.
> Um ein Bit an einem Port zu setzen verwendet man PORT(X), in deinem Fall
> PORTB. Dazu muss auch das DDRB Register richtig gesetzt sein.
> PIN(X) wird zum einlesen verwendet.
> Das mal als Hinweis.
>
> Setzt Du die Variable diceButtonPressed in der main irgendwann auf 0?
> Zeig mal den ganzen Code, sonst kann man Dir nicht wirklich helfen.
>
> Und den reti() im ISR, schmeiß bitt

von Martin L. (martin_l795)


Lesenswert?

Zum Pin B nochmal: Writing  a logic one to PINxn  toggles the  value  of 
PORTxn, independent on  the  value  of DDRxn.

von S. Landolt (Gast)


Lesenswert?

Immer die alte Leier, aber vielleicht unbekannt, da erst seit vorgestern 
dabei: das Programm auf das nötige Minimum reduzieren und dann im 
Original hier vorstellen.

von Thomas E. (thomase)


Lesenswert?

Martin Luerssen schrieb:
> ISR(EXT_INT0_vect) {
>
>   diceButtonPressed = 1;
>   PINB |= (1<<TEST_OUT_PIN); // Test-LED Interrupt erreicht
>   reti();
> }

Dein Programm hat keine ISR für INT0. Deswegen springt der Controller 
beim Auslösen des Interrupts auf 0 und fängt wieder von vorne an.

Der Vektor heisst 'INT0_vect'. 'EXT_INT0_vect' kennt der Compiler nicht. 
Dafür hast du auch eine Warnung bekommen. Warnungen sind nicht zum 
ignorieren da!

Also:
1
ISR(INT0_vect)

Und das reti() gehört nicht in die ISR, das wurde ja schon gesagt.

mfg.

: Bearbeitet durch User
von Stefan E. (sternst)


Lesenswert?

Thomas Eckmann schrieb:
> Der Vektor heisst 'INT0_vect'. 'EXT_INT0_vect' kennt der Compiler nicht.

Doch, beim Tiny24 heißt der genau so.

von Thomas E. (thomase)


Lesenswert?

Stefan Ernst schrieb:
> Doch, beim Tiny24 heißt der genau so.
1
/* Interrupt vectors */
2
/* Vector 0 is the reset vector */
3
#define EXT_INT0_vect_num  1
4
#define EXT_INT0_vect      _VECTOR(1)  /* External Interrupt Request 0 */

Welcher Knallkopp hat das denn verzapft?

Damit ist mein Post nicht mehr gültig.

mfg.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Thomas Eckmann schrieb:
> Welcher Knallkopp hat das denn verzapft?

Das Problem sich gelegentlich von Produkt zu Produkt ändernder 
Handler-Namen für die gleiche Sache durchzieht die gesamte 
Produktpalette.

von Dieter F. (Gast)


Lesenswert?

Martin Luerssen schrieb:
> Relevante Code-Teile

Hast Du ggf. noch weitere (und möglicherweise unbehandelte) Interrupts 
aktiviert?

von Bastler (Gast)


Lesenswert?

Ob TIM0_OVF_vect oder TIMER0_OVF_vect der richtige ist, kann man mit 
einem #ifdef leicht rausfinden (und so portablen Code, im AVR Umfeld, 
schreiben).
Die Makros ISR() und SIGNAL() setzen für die definierten Funktionen die 
Attribute "interrupt" oder "signal", die das AVR-Backend veranlaßt, ALLE 
benutzten Register zu sichern, nicht zu erwarten, daß in R1 kein 
einziges Bit gesetzt ist und zuguterletzt mit RETI statt RET zu enden.
 Das Makro reti() wird nur für "nacked" Interrupt-Funktionen gebraucht, 
denn dann macht der Compiler weder Rgistersichern/restore noch RET/RETI. 
Da darf der Prograbmmierer alles selber machen. Per asm(). Und er weiß 
hoffentlich was er tut. Sinnvoll wenn z.B. nur ein Bit in GPIORn gesetzt 
werden soll, dann wird die ISR deutlich kompakter. Und Leute mit 
Takt-Phobie hoffentlich ruhiger :-)

von Thomas E. (thomase)


Lesenswert?

A. K. schrieb:
> Das Problem sich gelegentlich von Produkt zu Produkt ändernder
> Handler-Namen für die gleiche Sache durchzieht die gesamte
> Produktpalette.

Nee, das ist in der 'iotn24a.h' so definiert. Im Datenblatt, sowohl bei 
24 als auch beim 24a, ist es wie gewohnt INT0. Dieser Vektor ist auch 
der einzige, der mit EXT_ versehen wurde.

TIM0 und TIMER0 und ... gibt es auch noch. Die stammen allerdings aus 
dem Datenblatt.

mfg.

von S. Landolt (Gast)


Lesenswert?

Ich hätte hier noch eine Geschichte von Paul Watzlawick, vielleicht 
kennt sie der eine oder andere ja noch nicht:
Ein Betrunkener kriecht um Mitternacht auf allen Vieren unter einer 
Straßenlaterne herum. Kommt ein Polizist vorbei: "Sie, was machen Sie 
denn da?" "Ich suche meinen Hausschlüssel." Jetzt suchen beide. Nach 
einer Viertelstunde fragt der Polizist: "Sagen Sie mal, sind Sie sicher, 
dass Sie den Schlüssel hier verloren haben?" Kommt die Antwort: "Nein, 
nicht hier, sondern dort drüben. Aber dort ist es viel zu dunkel zum 
Suchen."

von Peter D. (peda)


Lesenswert?

A. K. schrieb:
> Und das reti()?

Das zerdrischt Dir den Epilog des Handlers.
Maximal wäre ein return; erlaubt.

von S. Landolt (Gast)


Lesenswert?

Peter Dannegger schrieb:
> A. K. schrieb:
>> Und das reti()?
>
> Das zerdrischt Dir den Epilog des Handlers.
> Maximal wäre ein return; erlaubt.

Ich dachte, darum hätte er sich schon vor drei Stunden gekümmert:

Martin Luerssen schrieb:
> Danke erstmal, Reti rausschmeissen versuche ich mal.

von Martin L. (martin_l795)


Lesenswert?

Hallo allerseits,

vielen Dank erstmal. Eben nach Hause gekommen und geändert, das reti() 
war es tatsächlich, Rest war Ok und funktioniert wie gedacht.
Keine Ahnung mehr, wie ich da drauf gekommen bin, evtl. vom Assembler 
her in meinem Hirn hängengeblieben das reti.

Thread kann dann zu, nochmal danke an alle.

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
Noch kein Account? Hier anmelden.