Forum: Compiler & IDEs ATMEGA48A Variablen reset nach Interrupt Aufruf.


von Finn (Gast)


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);

    }

}

ISR(INT1_vect){

test=1;

}

von Andras H. (kyrk)


Lesenswert?

PORTC&=~(0b0111111);
    PORTD&=~(0b11100011);

Was ist damit? Das löscht doch die LEDs. Also praktisch hast du damit 
ein PWM gemacht.

Mal gucken ob die LED unter ossczi doch nicht kurz leuchten?

von Finn (Gast)


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.

von Andras H. (kyrk)


Lesenswert?

volatile uint8_t test;

mache mal den uint32.

von Norbert (der_norbert)


Lesenswert?

Wo kommt denn ›pwm‹ (in den Verzögerungsschleifen) her?

von Finn (Gast)


Lesenswert?

Habe jetzt mal uint32 und uint16 probiert aber hat keinen Unterschied 
gemacht.

von Jens N. (midibrain)


Lesenswert?

Welche programiersprache? Was ist PWM?

von Finn (Gast)


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 vom Autor gelöscht.
von Ob S. (Firma: 1984now) (observer)


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.

von Sebastian W. (wangnick)


Lesenswert?

Ob S. schrieb:
> Nur zwei primitive Regeln. Wende sie einfach an.

Hat er doch!

LG, Sebastian

von Sebastian W. (wangnick)


Lesenswert?

Finn schrieb:
> Die Variable PWM ist immer 1.

Und die Variable pwm, die dein Code benutzt?

LG, Sebastian

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Sebastian W. schrieb:

> Und die Variable pwm, die dein Code benutzt?

Ich sehe in diesem ganzen "Werk" nirgendwo eine Variable namens pwm. Bei 
der Anwendung üblicher C-Compiler kann daraus also schonmal kein 
Programm entstehen.

> Hat er doch!

Woher, zum Teufel, willst du das in vollständiger Absenz der 
Variablendeklaration wissen?

von Veit D. (devil-elec)


Lesenswert?

Hallo,

test ist volatile und ein Byte ist per se atomar. Was allerdings 
wirklich nirgends deklariert/definiert ist die Variable pmw, die in den 
for Schleifen verwendet wird. So wie eingangs gepostet sollte das nicht 
kompilieren. Irgend etwas fehlt.

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Veit D. schrieb:
> test ist volatile und ein Byte ist per se atomar.

jo, ich seh nur irgendwie nicht das nach dem einmaligen Setzen in der 
ISR dies auch mal wieder auf null gesetzt wird.

von Rolf M. (rmagnus)


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.

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Irgend W. schrieb:

> jo, ich seh nur irgendwie nicht das nach dem einmaligen Setzen in der
> ISR dies auch mal wieder auf null gesetzt wird.

Hinweis. Wenn dein Thread nicht zum Scherz degradieren soll, empfehle 
ich dir dringend auf die Fragen bzw. Fragezeichen der Helfer einzugehen 
und es nicht oberflächlich abzuhandeln.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.