ATMEGA48A Variablen reset nach Interrupt Aufruf.

Gast #7616958
Lesenswert?

Hallo, für ein Uniprojekt muss ich einen ATMEGA48A programmieren und habe beim herumprobieren ein Problem. Ich habe einen simples Programm geschrieben bei dem LEDS Leuchten nachdem ein Interrupt ausgeführt wird. Mein Problem ist aber das die LEDs nur leuchten während der Interrupt aktiv ist. Das muss also bedeuten das die Variable trotz volatile immer nach ende des Interrupts wieder auf 0 gesetzt wird. Im Simulator von Atmel Studio 7 funktioniert das Programm normal aber beim richtigen Controller nicht. Danke für etwaige Ideen und Lösungsvorschläge. Hier der Code:

#define F_CPU 1000000UL

#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>

#include <stdbool.h>

volatile uint8_t test;

int main(void)

{

EIMSK|=(1<<INT1); //Interrupt 1 enabled

EIMSK|=(1<<INT0); //Interrupt 0 enabled

PCMSK2|=(1<<PCINT20); //Pin Change Interrupt für Pin 20

PCICR|=(1<<PCIE2); //Pin Change Interrupt enabled

DDRD|=0b11100011;

DDRC|=0b0111111;

PORTD|=0b00011100; //Pullup für Eingänge wiederstände werden aktiviert

test=0;

sei();

while (1)

{

for(int i=0; i<=(20-pwm); i++){

_delay_us(100);

}

if (test==1)

{

PORTC|=0b0111111;

PORTD|=0b11100011;

}

for(int i=0; i<=pwm; i++){

_delay_us(100);

}

PORTC&=~(0b0111111);

PORTD&=~(0b11100011);

1
}

}

ISR(INT1_vect){

test=1;

}

Gast #7617004
Lesenswert?

Genau die LEDs leuchten ganz normal (flackern schnell da pwm) wenn man das if(test==1) weglässt. Mit dem If leuchten sie aber immer nur einmal ganz kurz auf, als würde die Variable test nach dem Interrupt wieder auf ihren Initialwert gesetzt werden. Ansonsten würde test ja nach dem Interrupt 1 bleiben und das Licht würde die ganze Zeit leuchten.

Gast #7617045
Lesenswert?

Programmiert ist es in C. Die Variable PWM ist immer 1. Ich habe jetzt einmal probiert das aktivieren der LEDS in den Interrupt zu verschieben also:

ISR(INT1_vect){

test++;

if (test==3)

{

PORTC|=0b0111111;

PORTD|=0b11100011;

}

}

Das funktioniert jetzt plötzlich wie ich es erwarte. Also die LEDS leuchten nach dreimaligen Aufruf des Interrupts. Das Problem liegt also irgendwie darin die Variable in der main Funktion korrekt aufzurufen.

Beitrag #7617047 wurde von einem Moderator gelöscht.
(Firma: 1984now) #7617208
Lesenswert?

Finn schrieb:

Das Problem liegt also irgendwie darin die Variable in der main Funktion korrekt aufzurufen.

Variablen werden nicht "aufgerufen", sondern gelesen oder geschrieben. Und beim AVR8 (auch der ATmega48A ist so einer), gibt es dabei zwei Sachen zu beachten:

  1. Wenn aus ISRs und aus main() darauf zugegriffen wird, muss man dem Compiler das mittels des Schlüsselworts volatile in der Variablendeklaration mitteilen. Das zwingt ihn dazu, wirklich für jede Operation auf diese Variable den Speicher zu verwenden, in dem sie steht und nicht den Inhalt irgendwelcher MCU-Register, in den er früher(tm) mal den Speicherinhalt geladen hat.

  2. Wenn die Variable breiter als 8Bit ist, muß man Zugriffe darauf aus dem main()-Kontext zusätzlich mit einem ATOMIC_BLOCK-Konstrukt gegen zwischenzeitliche Änderungen durch die ISR(s) schützen.

Nur zwei primitive Regeln. Wende sie einfach an. Beispiele findest du unzählige. Einfach mal Google benutzen.

#7617292
Lesenswert?

Finn schrieb:

Hier der Code:

Bitte die angegebenen Formatierungsregeln beachten!

Offenbar ist der gezeigte Code nicht der, den du auf dem µC laufen lässt, denn du verwendest eine Variable namens pwm, die nirgends definiert oder geschrieben wird. Du schaltest außerdem den Pin-Change-Interrupt und den INT 0 ein, definierst dafür aber keine ISRs. Das default-Verhalten, wenn ein solcher Interrupt ausgelöst wird, ist ein Reset des µC. Was mir weiter auffällt ist, dass du INT0 und INT1 auf level-Triggering eingestellt hast. Das heißt, deine ISR wird permanent immer wieder aufgerufen, solange der Pin auf low ist. Meist will man aber eher, dass die ISR nur bei jeder Änderung einmal aufgerufen wird.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren