Forum: Compiler & IDEs Interruptrotine: cli(); funzt nicht


von Tom (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

hab das unten aufgeführte Programm gschrieben.
Leider kann ich die Pin-changed Interruptrotine nicht disablen.
Müsste doch mit cli(); funktionieren.
Leider durchläuft er bei einem Interrupt die Rotine desöfteren.
Die Tasten sind nicht entprellt, möchte ich hinzufügen, was jedoch egal
sein müsste, da man ja beim ersten Durchlauf der ISR der Interrupt
disabled wird.

Bin über jeden Tip dankbar.

Im Voraus Danke!

Grüsse Tom

#include <avr\io.h>
#include <avr\signal.h>
#include <avr\interrupt.h>
#include <stdlib.h>
#include "init.h"
#include "display_4bit.h"

char nummer = 0;
BYTE nummer_buffer[2]={'0','0'};

INTERRUPT(SIG_PIN_CHANGE1)
    {
  cli( );
  nummer++;
    }

void Byte2Ascii(BYTE array[2],BYTE zahl)
    {
    array[0]= (zahl%10)|0x30;  // |0x30 für Ascii-Umwandlung
    array[1]= (zahl/10)|0x30;  // |0x30 für Ascii-Umwandlung
    }

void main (void)
    {
    DDRC=0x00;
    lcd_init();
    lcd_command_out(lcd_on);// Display ein
    sbi(PCICR, PCIE1); // PIN-CHASNGE-Interrupt aktivieren
    PCMSK1=0xFF;       // alle Eingängedes PortC für ISR aktivieren
    sei();         // Interrupts zulassen
    for (;;)          // Endlosschleife
        {
  lcd_string_out("Interuptnr. ",1);
        lcd_position_set(1,14);
  Byte2Ascii(nummer_buffer,nummer);
        lcd_data_out(nummer_buffer[1]); //Anzahl Durchläufe derISR
        lcd_data_out(nummer_buffer[0]); //Anzahl Durchläufe derISR
  }
    }

von OldBug (Gast)


Lesenswert?

Du kennst den Unterschied zwischen INTERRUPT und SIGNAL?
Falls nicht: benutze SIGNAL...

von Tom (Gast)


Lesenswert?

Auch mit SIGNAL kein disablen möglich.
Gibs zwischen SIGNAL und INTERRUPT einen Unterschied?

von Matthias (Gast)


Lesenswert?

Hi

bei einem reti wird das globale Interrup Flag immer gesetzt. cli(); hat
in einer ISR deshalb keine Wirkung.

Matthias

von OldBug (Gast)


Lesenswert?

Du solltest auch nicht das Globale-Interruptflag löschen, sondern den
Pin-Change-Interrupt ausschalten:

[..]
  PCICR &= ~(1 << PCIE1);
[..]

Und: Ja! Es gibt einen gewaltigen Unterschied zwischen INTERRUPT und
SIGNAL, steht aber genauestens in der Doku der avr-libc beschrieben...
Da steht übrigens auch, daß sbi/cbi und Co abgekündigt sind, also nicht
mehr verwenden. Lieber gleich an die "richtige" Schreibweise gewöhnen
:)

von Peter D. (peda)


Lesenswert?

cli() funktioniert und tut genau das, was es soll: alle Interrupts
disablen.

Und es tut auch nicht einen Fatz mehr, d.h. es setzt keine
Interruptflags zurück.
Wäre ja auch schlimm, dann könnte man nämlich keine Interrupts pollen
oder würde Interrupts verlieren.


Anders gesagt, wenn ein Interruptflag ausgelöst wurde und Du führst
nach 10 Jahren ein sei() aus, dann wird der Interrupt auch schön
abgearbeitet, genau wie es sein soll.

Will man das nicht, dann muß man vor der Freigabe das Interruptflag
löschen (auf 1 setzen).


Der Pin-Change Interupt ist bei den meisten AVRs ziemlich witzlos. Man
kann nicht die Pins auswählen und auch nicht erkennen, welcher Pin ihn
ausgelöst hat.
Er eignet sich daher nur zum Aufwachen des AVRs. Und nach dem Aufwachen
sollte man ihn sofort disablen, will man nicht mit Interrupts zugebombt
werden.


Peter

von Jörg Wunsch (Gast)


Lesenswert?

> cli() funktioniert und tut genau das, was es soll: alle Interrupts
> disablen.

Klar, aber innerhalb einer ISR ist das eine teure Form eines NOPs: die
Interrupts sind bereits abgeschaltet, und sie werden beim RETI
wieder zugeschaltet, unabhängig davon, wie viele Male der
Programmierer zwischendrin das bereits gelöschte Interruptflag nochmal
gelöscht hat.

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.