Allgemeines
Der ATMega16 hat drei Pins, die einen externen Interrupt auslösen können. Extern bedeuted in diesem Fall, dass die eigentliche Interruptquelle nicht innerhalb des Mikrocontrollers ist, sondern eben extern.
Pinbelegung
Die drei Pins sind in der folgenden Pinbelegung markiert.
INT0
- PORT D - Bit 2INT1
- PORT D - Bit 3INT2
- PORT B - Bit 2 (zusätzliche Mehrfachbelegung mit dem analogen Komperator)
Bei entsprechender Konfiguration kann ein Interrupt ausgelöst werden, wenn sich der Pegel am entsprechenden Pin ändert.
Register zur Konfiguration
MCUCR
Der Grund für das Auslösen eines Interrupts bei den beiden externen Interrupts INT0 und INT1 wird über das Register MCUCR
(MCU Control Register) gesteuert.
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Name | SM2 | SE | SM1 | SM0 | ISC11 | ISC10 | ISC01 | ISC00 |
Read/Write | R/W | R/W | R/W | R/W | R/W | R/W | R/W | R/W |
Init | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Dazu haben wir vier verschiedene Konfigurationsmöglichkeiten für INT0 und INT1:
ISCx1 | ISCx0 | Beschreibung |
---|---|---|
0 | 0 | Löst bei logisch 0 Pegel aus |
0 | 1 | Löst bei deiner Pegeländerung aus (steigende oder fallende Flanke) |
1 | 0 | Löst bei fallende Flanke (Pegeländerung von logisch '1' auf '0') |
1 | 1 | Löst bei steigender Flanke (Pegeländerung von logisch '0' auf '1') |
MCUCSR
Der externe Interrupt für INT2 wird über das Register MCUCSR
(MCU Control and Status Register) gesteuert.
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Name | JTD | ICS2 | - | JTRF | WDRF | BORF | EXTRF | PORF |
Read/Write | R/W | R/W | R | R/W | R/W | R/W | R/W | R/W |
Init | 0 | 0 | 0 | - | - | - | - | - |
Ist ISC2
auf logisch 0
wird der Interrupt bei einer fallenden Flanke ausgelöst. Bei logisch 1
wird entsprechend bei einer steigenden Flanke ausgelöst.
GICR
Die Freigabe der Interrupts erfolgt über das Register GICR
(General Interrupt Control Register).
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Name | INT1 | INT0 | INT2 | - | - | - | IVSEL | IVCE |
Read/Write | R/W | R/W | R/W | R | R | R | R/W | R/W |
Init | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Die Bits INT0, INT1 und INT2 aktivieren die Interruptfreigabe.
Für den Aufruf der entsprechenden Interruptrountine sind nun folgende Punkte notwendig:
- Das entsprechende Bit bei
GICR
ist gesetzt, damit der Interrupt freigegeben ist - Über
sei()
wurde die globale Interruptfreigabe aktiviert (siehe Interrupts im Skriptum) - Eine Pegeländerung entsprechend der Konfiguration unter
MCUCR
bzw.MCUCSR
tritt beim entsprechenden Pin auf
GIFR
Über dieses Register kann das Statusflag beim entsprechenden Interrupt abgefragt werden. Dies ist notwendig, wenn die Detektion einer Pegeländerung genutzt werden soll, aber keine Interrupt Service Routine aufgerufen werden soll.
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Name | INTF1 | INTF0 | INTF2 | - | - | - | - | - |
Read/Write | R/W | R/W | R/W | R | R | R | R | R |
Init | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Tritt die konfigurierte Pegeländerung auf wird das entsprechende INTFx
Flag gesetzt. Zurückgesetzt wird das Flag, indem entwededer die Interrupt Service Routine aufgerufen wurde oder indem man eine logische 1
an das entsprechende Bit schreibt.
Beispiel
In diesem Beispiel wird folgendes konfiguriert:
- INT0 reagiert auf eine fallende Flanke und nutzt die entsprechende Interrupt Service Routine
- INT1 reagiert auf jeden Pegelwechsel und fragt den Zustand per Polling über das GIFR Register ab
- INT2 wird nicht genutzt
Umsetzung:
#include <avr/interrupt.h> ISR(INT0_vect) { // Interrupt Service Routine für INT0 // ... } int main(void) { MCUCR=0x06; // entspricht 0b0000 01 10 -> INT0 löst bei fallender Flanke aus, INT1 bei jedem Pegelwechsel MCUCSR=0x00; // entspricht 0b0 0 000000 -> INT2 löst bei fallender Flanke aus (wird aber nicht genutzt) GICR=0x40; entspricht 0b010 00000 -> INT0 Interrupt ist freigegeben, INT1 und INT2 nicht sei(); // globale Interruptfreigabe while(1) { // Hauptschleife if (GIFR&0x80) { // überprüfe Zustand von INT1 GIFR|=0x80; // setze Flag für INT1 zurück // ... } // ... } return 0; }