Hi, habe nun also ein wenig mit den Interrupts gespielt. Im Anhang ein nettes kleines Demoprogramm, dass beide externen Interrupts bedient.
Kurzbeschreibung: Wird am Int0 Pin eine steigende Flanke produziert,
so wird Zustand des PortsB um 1 erhöht.
Wird INT1 ausgeloest, wird PortB einfach 0x0a aufgeprägt.
Funktioniert so weit ganz gut, nur ein paar Schönheitsfehler die denke ich
charakteristisch für Interrupts sind würde ich gerne noch geklärt wissen:
Beim Erhöhen von PortB mußte ich intervenieren, da der nicht einfach
ueberlief und wieder bei Null haengen blieb, sondern immer die oberen
beiden Bits "haengen" bleiben.
Die Sache mit dem Schalterprellen konnte ich nicht einfach dadurch beseitigen, dass ich den Interrupt in der entsprechenden ISR ausgeschaltet
habe. Abhilfe?
Code:
// Demoprogramm zur Verwendung von Interrupts am Beispiel der externen Interruptquellen (Int1 Int0)
// Autor: Bachmayer
// Review Status: NONE
//Wissenswertes zu Interrupts auf AVRs:
// Global Interrupt Enable I-Bit im GICR Register ist normalerweise LOW wenn Interupt ausgeführt wird
// Interrupts haben zwar eine Priorität, können sich aber normalerweise nicht gegenseitig unterbrechen
// Interrupt Schachtelung mittels manuellem I-Bit setzen möglich
// Information im Statusregister SREG geht bei Interruptausführung verloren wenn man nicht sorgetraegt
// Befehle: _SEI() = Set I Bit - Aktiviert Interruptfaehigkeit
// _CLI()= Clear I Bit - Schaltet Interruptfaehigkeit aus
// _SLEEP() = uC geht in den Sleep Modus und wartet auf naechsten Interrupt
//
//
// Die Verfuegbaren Interrupt Signale entnommen aus der io.h wo diese den entsprechenden Interruptvektoren zugeordnet werden:
// #define SIG_INTERRUPT0 _VECTOR(1)
// #define SIG_INTERRUPT1 _VECTOR(2)
// #define SIG_OUTPUT_COMPARE2 _VECTOR(3)
// #define SIG_OVERFLOW2 _VECTOR(4)
// #define SIG_INPUT_CAPTURE1 _VECTOR(5)
// #define SIG_OUTPUT_COMPARE1A _VECTOR(6)
// #define SIG_OUTPUT_COMPARE1B _VECTOR(7)
// #define SIG_OVERFLOW1 _VECTOR(8)
// #define SIG_OVERFLOW0 _VECTOR(9)
// #define SIG_SPI _VECTOR(10)
// #define SIG_UART_RECV _VECTOR(11)
// #define SIG_UART_DATA _VECTOR(12)
// #define SIG_UART_TRANS _VECTOR(13)
// #define SIG_ADC _VECTOR(14)
// #define SIG_EEPROM_READY _VECTOR(15)
// #define SIG_COMPARATOR _VECTOR(16)
// #define SIG_2WIRE_SERIAL _VECTOR(17)
// #define SIG_SPM_READY _VECTOR(18)
//
//
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>
int8_t m;
void main(void)
{
DDRB=0xff;
DDRD=0x00; // Kompletter D Port wird hier als Input definiert. Beachte, auch als Output Interrupt möglich!
//Konfiguration eines externen Interrupts (Alternativfunktion int0 int1 Pins) im MCUCR Register:
// ISC11/ISC10 fuer INT1; ISC01/ISC00 fuer INT0;
//ISC11 ISC10 Description
//0 0 The low level of INT1 generates an interrupt request.
//0 1 Any logical change on INT1 generates an interrupt request.
//1 0 The falling edge of INT1 generates an interrupt request.
//1 1 The rising edge of INT1 generates an interrupt request.
cli(); // i Bit in Statusregister gelöscht=> Interrupts deaktiviert
MCUCR=(1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00); // Definition der Ereignisse fuer die entsprechenden Interrupts
GICR=(1<<INT1)|(1<<INT0); // Nun sind die Interrupts scharf
sei(); // i Bit in Statusregister gesetzt=> Interrupts koennen ab jetzt auftreten
for(;;)
{
}
}
SIGNAL(SIG_INTERRUPT0) // ISR fuer die erste Service Routine: Zaehlt einfach den PortB hoch
{
GICR=0x00; //A: Versuch Schalterprellen zu beseitigen, maessiger Erfolg ...
m=PINB;
if (m>0x2e) {m=0;}
PORTB=m+1;
_delay_ms(250); // warten... um garantiert nicht schneller zu sein wie Schalterprellen...
_delay_ms(250); //
GICR=(1<<INT1)|(1<<INT0); // A: Externe Interrupts wieder aktiviert
}
SIGNAL(SIG_INTERRUPT1) // ISR fuer zweiten externen Interrupt: Setzt einfach charakteristisches Muster...
{
PORTB=0x0a;
}
In jedem Falle vielen vielen herzlichen Dank an izaseba!
uC
Lesezeichen