PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] ATMEGA32 Interrupt CLI stoppt Interrupts nicht



Tux12Fun
22.12.2019, 16:25
Hallo,

Ich habe da ein kleines Problem und hoffe auf eure Hilfe.

Mein Schaltplan



Taster +5V
|
ATMEGA32 PIN16 (INT0) ------ 1MOhm --- (GND)
PIN40 (PA) ------ 150 Ohm --- Duo LED --- (GND)





#define MCU atmega32
#define F_CPU 16000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <inttypes.h>

// Direction Registers
DDRA = 0xff; // LED Block A
DDRC = 0xff; // LED Block C

DDRD &= ~(1 << PIND7); // IR-LED to INPUT
// LED Ports to LOW
PORTA = 0x00;
PORTC = 0x00;
PORTD = 0x00;

//Enable Intrerrupts for Intrustion Detection (INT0)
sei(); // Interrupts zur Verfügung stellen
GICR =(1<<INT0); // INT0 bereitstellen
MCUCR =(3<<ISC00); // INT0 für steigende Flanken einstellen

while(1){}
}

// Interrupt INT0
ISR(INT0_vect){
PORTA ^= 1<<PINA0; //die LED wird umgeschaltet
cli(); //Interrupts deaktivieren
// Ab jetzt sollte keine Änderung mehr möglich sein.
}


Meine Annahme nach cli() sind die Interrupts disabled und die Led bleibt bei mehrmaligem Tastendruck in dem Status.
Dies passiert aber nicht. Die Led wechselt weiter fleißig zwischen an und aus. Was mache ich da falsch?

Klebwax
22.12.2019, 17:01
Deine Schaltung ist ungewöhnlich. Taster läßt man gewöhnlich gegen GND arbeiten. Und 1MΩ entspricht dem Widerstand einer schmutzigen Leiterplatte, ist also viel zu groß. Ich kenne deinen Prozessor nicht, viele haben aber eingebaute, einschaltbare Pullups, da braucht man nur eine Taste nach GND. Und statt 150Ω würd ich 470Ω nehmen. Damit leuchten moderne LEDs auch und man stresst den armen µC nicht so.

Man sollte es unterlassen, im Interrupthandler selbst an den Interrupten rumzudrehen. Das hatte ich schon an anderen Stellen mehrmals geschrieben. Beim Eintritt in den Handler sperrt der µC die Interrupte automatisch, am Ende erlaubt er sie wieder. Das cli() wirkt also nur bis zur schließenden geschweiften Klammer des Handlers. Es ist außerdem wirkungslos, da die Interrupte im Handler sowieso gesperrt sind.

Mal abgesehen von den "merkwürdigen" Kommentaren (sei() erlaubt Interrupte, schaltet sie ein) würd ich die Reihenfolge ändern. Erstmal alles einstellen, GICR und MCUCR setzen und dann Interrupte erlauben. Erst den Gang rein und dann die Kupplung kommen lassen.

MfG Klebwax

Tux12Fun
22.12.2019, 17:27
Hallo Klebwax

Danke für deine Antwort ich habe jetzt mal wie folgt umgebaut.



int detect = 0;
int main(){
// Direction Registers
DDRA = 0xff; // LED Block A
DDRC = 0xff; // LED Block C

DDRD &= ~(1 << PIND7); // IR-LED to INPUT

// Ports to LOW
PORTA = 0x00;
PORTC = 0x00;
PORTD = 0x00;

// :-) Gang einlegen
PORTD |= (1<<PD2); // Pullup auf INT0 (PD2) an
GICR =(1<<INT0); // INT0 bereitstellen
MCUCR =(3<<ISC00); // INT0 für steigende Flanke einstellen
// Los fahren
sei(); // Interrupts aktivieren

while(1){
if (detect == 1){
cli(); // Interrupts deaktivieren (halten)
detect=0;
}
}
}
// Interrupt INT0
ISR(INT0_vect){
PORTA ^= 1<<PINA0; //die LED wird umgeschaltet
detect = 1;
}


Der INT0 wird jetzt gegen GND getastet.
Zum Test ist das Ganze noch so mit der LED an PINA.
Damit ich sehen kann ob der Interrupt wirklich deaktiviert wird.

Ziel ist es über den Interrupt das öffnen des Gerätes zu erkennen.

Die LED Widerstände werde ich noch ändern.

Klebwax
22.12.2019, 17:51
Statt alle Interrupte ganz abzuschalten, würde ich sie erstmal mit cli() auschalten, dann INT0 deaktivieren, und sie wieder einschalten. Dann geht der Rest des Systems, der sicher noch weitere Interrupte haben wird, weiter.

MfG Klebwax

Tux12Fun
22.12.2019, 18:11
Das werde ich doch gleich mal testen. Mein debuging zeigt mir gerade dass meine Variable "detect" irgendwie nie den
Wert ändert ??? Warum auch immer. PA6 wird nämlich nicht aktiviert und das ist mehr als seltsam. Damit wird dann
auch kein cli() aufgerufen und das Phänomen wäre erklärbar, dass damit der Interrupt aktiv bleibt. Die ISR wird allerings
angesprochen. Die LED an PA0 ändert ihren Status. die While schleife wird auch erreicht. Schiebe ich die PA6 LED dort hin
leuchtet sie.



#define MCU atmega32
#define F_CPU 16000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <avr/sleep.h>
#include <avr/power.h>

int detect = 0;

int main(void){
// Direction Registers
DDRA = 0xff; // LED Block A
DDRC = 0xff; // LED Block C

DDRD &= ~(1 << PIND7); // IR-LED to INPUT

// Ports to LOW
PORTA = 0x00;
PORTC = 0x00;
PORTD = 0x00;

PORTD |= (1<<PD2); // Pullup auf INT0 (PD2) an
GICR |=(1<<INT0); // INT0 bereitstellen
MCUCR |=(2<<ISC00); // INT0 für fallende Flanke einstellen
sei(); // Interrupts aktivieren
while(1){
if (detect == 1){
PORTA |= (1<<PA6);
cli(); // Interrupts deaktivieren
}
}

return 0;
}

// Interrupt INT0
ISR(INT0_vect){
detect = 1;
PORTA ^= 1<<PINA0; //die LED wird umgeschaltet
}


- - - Aktualisiert - - -

Ich habs geschafft, das ganze ist ein Compiler Bug :-( sobald ich mit -Os übersetze ist es Buggy mit -O0 ist alles in Ordnung.

Da kann ich ja ewig suchen. Ich hab jetzt ein paar mal hin und her probiert und es lässt sich reproduzieren :-(

Searcher
22.12.2019, 18:31
Ich habs geschafft, das ganze ist ein Compiler Bug :-( sobald ich mit -Os übersetze ist es Buggy mit -O0 ist alles in Ordnung.
Das ist kein Bug sondern ein Feature. detect muß als volatile markiert werden wenn es in der isr verändert werden können soll:
https://rn-wissen.de/wiki/index.php/Fallstricke_bei_der_C-Programmierung#Probleme_mit_volatile

Gruß
Searcher

021aet04
22.12.2019, 18:38
Das ist kein Bug. Die Variable wird wegoptimiert. Der compiler denkt das der Interrupt nicht ausgeführt wird und dadurch die Variable unnötig Platz verschwendet (weil diese nicht gesetzt wird). Du kannst dem Compiler aber sagen das er diese Variable nicht wegoptimieren darf indem du "volatile" verwendest.

Z.B.: volatile int detect=0;

Wenn du es so schreibst wird es funktionieren. Wenn du es debuggst, kannst du die Variable beobachten. Normalerweise steht dann "optimized away".

MfG Hannes

Tux12Fun
22.12.2019, 18:51
Oh vielen Dank da habe ich echt etwas dazu gelernt.