Zille
20.01.2014, 15:22
Hallo zusamen,
ich habe ein Problem mit meiner ISR.
Ich habe im Wesentlichen ein Programm geschrieben, welches bei Auslösen von Int0 eine Variable incrementiert und bei Auslösen von Int1 diese decrimentiert. Soweit läuft es auch einwandfrei.
Nun habe ich allerdings den Fehler, dass hin und wieder bei Betätigung von einem der Interrupts anstatt "1" hinzu bzw abgezogen gleich "2" hinzu bzw abgezogen wird.
In den ISR habe ich bewusst nun eine delaytime von 10000ms eingetragen. Betätige ich den Schließenkontakt nun z.B 5x innerhalb der delaytime, so wird die Variable gleich um "5" verändert. Das möchte ich so natürlich nicht ;)
Daher meine Frage: Wie kann ich es verhindern, dass die ISR von z.B Int0 wärend Sie ausgeführt wird sich die weiteren Interrupts NICHT merkt und mit verarbeitet?
P.S.: cli() steht in jeder ISR direkt am Anfang.
Hier mein Code
/*
* Drehkreuz.c
*
* Created: 06.01.2014 15:53:43
* Author: Zille
*/
#include <avr/io.h>
#include <avr/interrupt.h> // Einbindungen
#include <avr/delay.h>
#include "lcd-routines.h"
#define F_CPU 8000000 // 8MHz Takt
volatile float Besucher_gesamt=0; // Speicher kostet ja nichts ;)
volatile float Besucher_aktuell=0;
char Ausgabe_aktuell[4]; // Für Ascii umwandlung
char Ausgabe_gesamt[4];
int main(void)
{
DDRD = 0b00100011; // PD0,1,5-->LEDs PD2,3,4--> Schließerkontakte,tastend
MCUCR |= 0b00001010; // Flankenauswahl fallende Flanke
GICR |= 0b11000000; // Int0 und Int1 freischalten
lcd_init(); // Display initialisieren
sei(); // Interrupts erlauben
while(1)
{
lcd_clear(); // Display löschen
dtostrf(Besucher_aktuell,4,0,Ausgabe_aktuell); // Double to String umwandeln --> fürs Display
lcd_string(Ausgabe_aktuell); // Ausgabe Inhalt Variable
lcd_string("Besucher");
lcd_setcursor(0,2); // Eine Zeiler tiefer im LCD springen
dtostrf(Besucher_gesamt,4,0,Ausgabe_gesamt);
lcd_string(Ausgabe_gesamt);
lcd_string("Insgesamt");
if (bit_is_set(PIND,4)) // Reset Taster
{
Besucher_aktuell=0;
Besucher_gesamt=0;
}
_delay_ms(100); // Verzug
}
}
ISR(INT0_vect) //Schaltkontakt für eingehende Besucher
{
cli();
Besucher_aktuell++;
Besucher_gesamt++;
PORTD |= (1<<PD5);
_delay_ms(10000); // Verzugzeit bewusst hoch gewählt um Problem besser darstellen zu können
PORTD &= ~(1<<PD5);
sei();
}
ISR(INT1_vect) // Schaltkontakt für ausgehende Besucher
{
Besucher_aktuell--;
if (Besucher_aktuell<0)
{
Besucher_aktuell=0;
}
PORTD |= (1<<PD1);
_delay_ms(10000); // Verzugzeit bewusst hoch gewählt um Problem besser darstellen zu können
PORTD &= ~(1<<PD1);
}
Danke im Vorraus :)
Gruß Zille
ich habe ein Problem mit meiner ISR.
Ich habe im Wesentlichen ein Programm geschrieben, welches bei Auslösen von Int0 eine Variable incrementiert und bei Auslösen von Int1 diese decrimentiert. Soweit läuft es auch einwandfrei.
Nun habe ich allerdings den Fehler, dass hin und wieder bei Betätigung von einem der Interrupts anstatt "1" hinzu bzw abgezogen gleich "2" hinzu bzw abgezogen wird.
In den ISR habe ich bewusst nun eine delaytime von 10000ms eingetragen. Betätige ich den Schließenkontakt nun z.B 5x innerhalb der delaytime, so wird die Variable gleich um "5" verändert. Das möchte ich so natürlich nicht ;)
Daher meine Frage: Wie kann ich es verhindern, dass die ISR von z.B Int0 wärend Sie ausgeführt wird sich die weiteren Interrupts NICHT merkt und mit verarbeitet?
P.S.: cli() steht in jeder ISR direkt am Anfang.
Hier mein Code
/*
* Drehkreuz.c
*
* Created: 06.01.2014 15:53:43
* Author: Zille
*/
#include <avr/io.h>
#include <avr/interrupt.h> // Einbindungen
#include <avr/delay.h>
#include "lcd-routines.h"
#define F_CPU 8000000 // 8MHz Takt
volatile float Besucher_gesamt=0; // Speicher kostet ja nichts ;)
volatile float Besucher_aktuell=0;
char Ausgabe_aktuell[4]; // Für Ascii umwandlung
char Ausgabe_gesamt[4];
int main(void)
{
DDRD = 0b00100011; // PD0,1,5-->LEDs PD2,3,4--> Schließerkontakte,tastend
MCUCR |= 0b00001010; // Flankenauswahl fallende Flanke
GICR |= 0b11000000; // Int0 und Int1 freischalten
lcd_init(); // Display initialisieren
sei(); // Interrupts erlauben
while(1)
{
lcd_clear(); // Display löschen
dtostrf(Besucher_aktuell,4,0,Ausgabe_aktuell); // Double to String umwandeln --> fürs Display
lcd_string(Ausgabe_aktuell); // Ausgabe Inhalt Variable
lcd_string("Besucher");
lcd_setcursor(0,2); // Eine Zeiler tiefer im LCD springen
dtostrf(Besucher_gesamt,4,0,Ausgabe_gesamt);
lcd_string(Ausgabe_gesamt);
lcd_string("Insgesamt");
if (bit_is_set(PIND,4)) // Reset Taster
{
Besucher_aktuell=0;
Besucher_gesamt=0;
}
_delay_ms(100); // Verzug
}
}
ISR(INT0_vect) //Schaltkontakt für eingehende Besucher
{
cli();
Besucher_aktuell++;
Besucher_gesamt++;
PORTD |= (1<<PD5);
_delay_ms(10000); // Verzugzeit bewusst hoch gewählt um Problem besser darstellen zu können
PORTD &= ~(1<<PD5);
sei();
}
ISR(INT1_vect) // Schaltkontakt für ausgehende Besucher
{
Besucher_aktuell--;
if (Besucher_aktuell<0)
{
Besucher_aktuell=0;
}
PORTD |= (1<<PD1);
_delay_ms(10000); // Verzugzeit bewusst hoch gewählt um Problem besser darstellen zu können
PORTD &= ~(1<<PD1);
}
Danke im Vorraus :)
Gruß Zille