Forum: Mikrocontroller und Digitale Elektronik Anweisung für Interrupt


von Björn (Gast)


Lesenswert?

Hallo,

wie kann ich ein Interrupt zu einem bestimmten Zeitpunkt erst starten?
z.B. nach einer Switch Anweisung.

Hab zwei Interrupts in meinem Programm. Das eine wird gestartet sobald
das UART Receive Flag gesetzt wird, also Daten ankommen. Da hab ich
dann eine Switch Anweisung das je nach ankommenden Wert etwas
ausgeführt wird. Kann ich in der Switch Anweisung auch angeben, das bei
einem bestimmten Wert erst das andere Interrupt gestartet wird....??

von Bernhard S. (bernhard)


Lesenswert?

Kein Problem, Du gibst erst den entsprechenden Interrupt frei, wenn Du
Ihn benötigst.

von Wolfgang Horn (Gast)


Lesenswert?

Hi, Björn,

DU startest keinen Interrupt. Nie. Sondern irgendein Hardware-Ereignis
wie eben ReceiveComplete.
In dieser Interrupt zu warten, bis irgendein ein anderes externes Gerät
etwas tut, wäre ziemlich unzweckmäßig, da wäre der Prozessor vielleicht
sehr lange in Wartestellung.

Sondern Du holst das Zeichen nur ab und bist wieder in der
Main-Routine.
Schau Dir ein paar Beispiel-Programmme an.

Ciao
Wolfgang Horn

von Björn (Gast)


Lesenswert?

Aber mit welchem Befehl kann ich einen bestimmten Intterupt
freigeben...??

Ist bestimmt jetzt voll simpel, aber ich kapier oder weiß es
nicht.....!!

von Wolfgang Horn (Gast)


Lesenswert?

Hi, Björn,

indem Du im UCSRnB beispielsweise RXCIEn: RX Complete Interrupt Enable
setzt.
Bei der Initialisierung muß noch mehr passieren, Du findest
Beispielprogramme im Datenblatt zu den Atmega.

Ciao
Wolfgang Horn

von ecslowhand (Gast)


Lesenswert?

Nicht mit Befehlen, sondern mit setzen entsprechender Flags.

Du setzt ja auch bei der UART-Geschichte das RXCIE-Flag, also das Flag,
das einen IRQ auslöst, wenn ein Zeichen im Empfangsbuffer vorhanden
ist.

LG EC

von ecslowhand (Gast)


Lesenswert?

Mist...Wolfgang war schneller.....

von Peter D. (peda)


Lesenswert?

"Aber mit welchem Befehl kann ich einen bestimmten Intterupt
freigeben...??"

Mit garkeinem.

Jede Interruptquelle hat in ihren Konfigurationsregistern ein
Enable-Bit, das mußt Du setzen.


Peter

von Björn (Gast)


Lesenswert?

Hi,

also das mit den Flags beim UART funktioniert und hab ich auch
verstanden. Senden und empfangen klappt beides wunderbar.

Nun wollte ich noch ein Blinklicht dazu nehmen, welches bei einem
bestimmten über UART empfangenen Wert anfängt zu blinken.

Das hab ich so gemacht:

SIGNAL(SIG_OUTPUT_COMPARE1A)
{
    uint16_t count;

    // irq_count um 1 erhöhen und...
    count = 1+irq_count;

    // ...alle 1000 IRQs die LED blinken
    if (count >= INTERRUPTS_PER_SECOND)
    {
        count = 0;
        PORT_LED ^= (1 << PAD_LED);
    }

    irq_count = count;
}

Das Blinken funktioniert auch, nur leider die ganze Zeit. Die LED soll
aber erst blinken, wenn ein entsprechendes Zeichen gsendet wird!

von Peter D. (peda)


Lesenswert?

P.S.:

Das heißt aber nicht, daß dann erst die Interruptquelle aktiv wird.

Kam ein Interruptereignis (z.B. Byte empfangen) und Du setzt erst nach
10 Jahren das Enable-Bit, dann kriegst Du auch sofort den Interrupt auf
das Ereignis von vor 10 Jahren.

Will man das nicht, muß man unmittelbar vor der Freigabe erst das
Interrupt-pending-bit löschen, was bei den AVRs blöderweise Bit setzen
bedeutet (beliebte Fallgrube für 100% aller AVR-Anfänger).


Peter

von Karl heinz B. (kbucheg)


Lesenswert?

> Das Blinken funktioniert auch, nur leider die ganze Zeit. Die LED
> soll aber erst blinken, wenn ein entsprechendes Zeichen gsendet
> wird!

In dem konkreten Fall hast du 2 Möglichkeiten.

Warum blinkt denn die LED?
Weil da ein Timer läuft der stänidg hochzählt und
irgendwann das Output Compare Ereignis auslöst. Bei der
Behandlung dieses Ereignisses wird dann das Blinken
geregelt.

Möglichkeit 1:
  Wenn der Timer nicht läuft, tritt auch kein Output Compare
  auf und folgerichtig blinkt auch keine LED.

  Jetzt schau dir nochmal an, wie du den Timer initialisiert hast.
  Irgendwann hast du mal den Vorteiler für den Timer eingestellt.
  Dann nochmal Blick ins Handbuch: Es gibt eine bestimmte Stellung
  der Vorteiler-Bits, die bewirken, dass der Timer nicht läuft.
  Wenn das Programm hochfährt stellst du genau das ein: Timer
  läuft nicht -> LED blinkt nicht. Kommt dann das Zeichen über
  die UART wird der Vorteiler eingeschaltet, der Timer läuft,
  die Output Compare Ereignisse kommen durch -> LED blinkt

Möglichkeit 2:
  Mann muss ja nicht gleich mit Kanonen auf Spatzen schiessen.
  Der Timer kann ja durchaus laufen, nur sollen halt die Output
  Compare Ereignisse keinen Interrupt auslösen.
  Wieder: Beim Hochfahren hast du irgendwann das Bit im
  Konfigurationsregister gesetzt, dass dem µC mitteilt, dass er
  bei Auftreten des Output Compare Ereignisses die Interrupt
  Funktion anspringen soll.
  Das nimmst du dort weg und setrzt dieses Bit erst dann, wenn über
  die UART das entsprechende Zeichen angekommen ist.

Eigentlich ganz einfach, oder?

  Vorteiler

von Björn (Gast)


Lesenswert?

Hey, war echt ganz einfach....!!!

Hat sofort geklappt....!!

Nur soll die LED, wenn die Taste erneut gedrückt wird auch wieder
ausgehen.....

von Karl heinz B. (kbucheg)


Lesenswert?

> Nur soll die LED, wenn die Taste erneut gedrückt wird auch wieder
> ausgehen.....

Das sollte jetzt aber kein Problem mehr sein :-)
Du machst einfach alles rückgängig, was du beim Einschalten
gemacht hast.

von Björn (Gast)


Lesenswert?

Stimmt, ne if Abfrage und nun klappt alles bestens.....!!!

Wie kann ich diese Stück umschreiben?

void moveservo(char pos)
{
  for(int yy=0;yy<7;yy++)
  {
    PORTB=1;              for(int i=0;i<pos;i++)
    delay_20us();

    PORTB=0;
    for(int i=0;i<(1500-pos);i++)              delay_20us();
       }
}

Krieg immer ne Fehlermeldung.....

von johnny.m (Gast)


Lesenswert?

> for(int i=0;i<pos;i++)
In ANSI-C müssen Variablen am Anfang eines Blocks deklariert werden.
Also besser:
void moveservo(char pos)
{
    int i, yy;
    for(yy = 0; yy < 7; yy++)
    {
        PORTB = 1;
        for(i = 0; i < pos; i++)
            delay_20us();
    //usw...
    }
}

von Björn (Gast)


Lesenswert?

Danke,

bekomme aber immer noch diese Fehlermeldung:

../Servo.c:83: Fehler: Anfangsdeklaration in »for«-Schleife
außerhalb C99-Modus verwendet

Hab schon versucht das Makefile zu ändern..... klappt aber nicht...!!

von johnny.m (Gast)


Lesenswert?

Du musst aus allen for-Schleifen die Variablendeklarationen rausnehmen
oder im Makefile c99 einstellen, dann gehts auch so...

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.