avr ersterer schritt
  Interrupts mit dem AVR GCC Compiler (WinAVR)
 
Interrupts mit dem AVR GCC Compiler (WinAVR)

Funktionen zur Interrupt-Verarbeitung werden in den Includedateien interrupt.h der avr-libc zur Verfügung gestellt (bei älterem Quellcode zusätzlich signal.h).

// fuer sei(), cli() und ISR():
#include <avr/interrupt.h> 

Das Makro sei() schaltet die Interrupts ein. Eigentlich wird nichts anderes gemacht, als das Global Interrupt Enable Bit im Status Register gesetzt.

    sei();

Das Makro cli() schaltet die Interrupts aus, oder anders gesagt, das Global Interrupt Enable Bit im Status Register wird gelöscht.

    cli();

Oft steht man vor der Aufgabe, dass eine Codesequenz nicht unterbrochen werden darf. Es liegt dann nahe, zu Beginn dieser Sequenz ein cli() und am Ende ein sei() einzufügen. Dies ist jedoch ungünstig, wenn die Interrupts vor Aufruf der Sequenz deaktiviert waren und danach auch weiterhin deaktiviert bleiben sollen. Ein sei() würde ungeachtet des vorherigen Zustands die Interrupts aktivieren, was zu unerwünschten Seiteneffekten führen kann. Die aus dem folgenden Beispiel ersichtliche Vorgehensweise ist in solchen Fällen vorzuziehen:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
 
//...
 
void NichtUnterbrechenBitte(void)
{
   uint8_t tmp_sreg;  // temporaerer Speicher fuer das Statusregister
 
   tmp_sreg = SREG;   // Statusregister (also auch das I-Flag darin) sichern
   cli();             // Interrupts global deaktivieren
 
   /* hier "unterbrechnungsfreier" Code */
 
   /* Beispiel Anfang
     JTAG-Interface eines ATmega16 per Software deaktivieren 
     und damit die JTAG-Pins an PORTC für "general I/O" nutzbar machen
     ohne die JTAG-Fuse-Bit zu aendern. Dazu ist eine "timed sequence"
     einzuhalten (vgl Datenblatt ATmega16, Stand 10/04, S. 229): 
     Das JTD-Bit muss zweimal innerhalb von 4 Taktzyklen geschrieben 
     werden. Ein Interrupt zwischen den beiden Schreibzugriffen wuerde 
     die erforderliche Sequenz "brechen", das JTAG-Interface bliebe
     weiterhin aktiv und die IO-Pins weiterhin für JTAG reserviert. */
 
   MCUCSR |= (1<<JTD);
   MCUCSR |= (1<<JTD); // 2 mal in Folge ,vgl. Datenblatt fuer mehr Information
 
   /* Beispiel Ende */
  
   SREG = tmp_sreg;     // Status-Register wieder herstellen 
                      // somit auch das I-Flag auf gesicherten Zustand setzen
}
 
void NichtSoGut(void)
{
   cli();
   
   /* hier "unterbrechnungsfreier" Code */
   
   sei();
}
 
 
int main(void)
{
   //...
 
   cli();  
   // Interrupts global deaktiviert 
 
   NichtUnterbrechenBitte();
   // auch nach Aufruf der Funktion deaktiviert
 
   sei();
   // Interrupts global aktiviert 
 
   NichtUnterbrechenBitte();
   // weiterhin aktiviert
   //...
 
   /* Verdeutlichung der unguenstigen Vorgehensweise mit cli/sei: */
   cli();  
   // Interrupts jetzt global deaktiviert 
 
   NichtSoGut();
   // nach Aufruf der Funktion sind Interrupts global aktiviert 
   // dies ist mglw. ungewollt!
   //...
   
}


Zu den aktivierten Interrupts ist eine Funktion zu programmieren, deren Code aufgerufen wird, wenn der betreffende Interrupt auftritt (Interrupt-Handler, Interrupt-Service-Routine). Dazu existiert die Definition (ein Makro) ISR.

 
  Heute waren schon 1 Besucher (9 Hits) hier!  
 
Diese Webseite wurde kostenlos mit Homepage-Baukasten.de erstellt. Willst du auch eine eigene Webseite?
Gratis anmelden