Verständnisproblem ISR am Attiny24

OP #4155929
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...
Gast #4155948
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.
OP #4155957
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
#4156005
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.
Gast #4156026
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 :-)
#4156072
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.
Gast #4156082
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."
OP #4156541
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren