mit Interrupt globale Variablen verändern

Gast #77995
Lesenswert?

Hi,

ich verwende gcc-avr unter Linux und möchte nun ein Programm schreiben,
bei dem durch ein Interruptaufruf eine Variable verändert wird. Diese
veränderte Variable soll dann in anderen Funktionen (*hier die main
Funktion) ausgewertet werden. Leider funktioniert das Programm so
nicht! An was liegt das? Wenn ich die Variable hour erst in der main
deklariere funktioniert zwar die Abfrage, dann erkennt aber die
Interrupt routine die Variable nicht mehr.

hier mein Programm:

/*dcf77 Funkuhr*/

#include <avr/io.h>
#include <avr/signal.h>


char hour=13; // globale Variable


void initialisation(void)
{
DDRC=0xFF; //PORTC als Ausgang
PORTC=0xFF; //alle LEDs aus
}


INTERRUPT(SIG_OVERFLOW0)//Interrupt Timer0 Overflow
{
 //... soll hier später die Variable hour verändern
}


int main (void)
{
initialisation();


if(hour==13) // hier die Abfrage der globalen Variable
{
PORTC=0x00;
}

return 0;
}

Eigentlich sollten ja nun die LEDs angehen, da die globale Variable 13
ist, tuts abba nicht.  Hat jemand ne Ahnung?

Danke
Gruss Bartman
Gast #77996
Lesenswert?

Versuche es mal mit
char volatile hour= 13;

Das volatile sorgt dafür, dass die Register immer sofort zurück in den
SRAM geschrieben werden.
Ansonsten: nachdem portc eingeschaltet wurde, wo springt das Prog dann
hin? wieder zum Anfang? das würde die LEDs ja erstmal wieder
ausschalten.

Ansonsten würde mich mal interresieren, wie ein makefile zum
compilieren unter Linux aussehen muss. Habe bisher nur unter Windows
compilieren können.
Gast #77998
Lesenswert?

"Das volatile sorgt dafür, dass die Register immer sofort zurück in den
SRAM geschrieben werden."

Das ist falsch. Volatile verhindert, dass der Compiler beim Optimieren
die Variable anfasst.
In obigem Beispiel wird sie also gar nicht erst angelegt.

Was das Makefile angeht, so habe ich ein einziges für Windows und
Linux. Das sollte gleich sein, es sei denn, Du rufts irgendwelche
Windowsprogramme auf, aber auch das kannst Du mit verschiedenen
Make-Targets umgehen.
Gast #77999
Lesenswert?

Hi,

ich habe das Programm laut euren Hinweisen modifiziert, aber leider
ohne erfolg... hmmm an was könnte das denn noch liegen?

/*dcf77 Funkuhr*/

#include <avr/io.h>
#include <avr/signal.h>


char volatile hour= 13;


void initialisation(void)
{
DDRC=0xFF; //PORTC als Ausgang
PORTC=0xFF; //alle LEDs aus
}




int main (void)
{
initialisation();

while(1)
{

  if(hour==13)
  {
  PORTC=0x00;
  }

}

return 0;
}



PS.:
So sieht mein Makefile aus:

#Makefile für dcf77

dcf77.hex: dcf77.out
  avr-objcopy -j .text -O ihex dcf77.out dcf77.hex
dcf77.out: dcf77.o
  avr-gcc -g -mmcu=at90s8515 -o dcf77.out dcf77.o
dcf77.o: dcf77.c
  avr-gcc -g -Os -mmcu=at90s8515 -c dcf77.c

clean:
  rm -rf *.o *.out

erase:
  uisp -dprog=stk200 -dlpt=/dev/parport0 -dpart=AT90S8515 --erase

upload:
  uisp -dprog=stk200 -dlpt=/dev/parport0 -dpart=AT90S8515 --upload
if=dcf77.hex
Gast #78000
Lesenswert?

Bzw.wenn die gar nicht erst angelegt wird, wie kann ich das ganze am
Besten angehen um wie gesagt durch nen Interrupt ein Variable zu
verändern, die ich dann in anderen Funktionen weiter auswerte.
Vielleicht hat ja jemand ein Programm Beispiel.
Immerhin kann das Problem ja nicht unbekannt sein...
Also Jungs, lasst mich bitte nicht hängen.
Gast #78001
Lesenswert?

Ich hab etwas rausgefunden. Die Variable lässt sich offenbar nicht mit
dem Aufruf volatile char hour=13; definieren. Erst bei einer Definition
durch den Interrupt mit einem Wert war dieser auch in der main Funktion
verfügbar.

Der Eintrag volatile char hour;
      hour=13;

global eingetragen brachte sogar beim kompilieren eine Fehlermeldung:
  avr-gcc -g -Os -mmcu=at90s8515 -c dcf77.c
dcf77.c:8: error: conflicting types for `hour'
dcf77.c:7: error: previous declaration of `hour'
dcf77.c:8: warning: data definition has no type or storage class
make: *** [dcf77.o] Fehler 1

Warum lässt sich die Variable nur global deklarieren, aber nicht
definieren, also mit einem Wert belegen?
Gast #78003
Lesenswert?

In der main ist die Variable halt nicht für die Interruptfunktion
verfügbar. Hmmm ich mache es jetzt über eine Initialisierungsfunktion,
in der ich dann (beim Aufruf dieser in der main ) der Variable einen
Wert zuweise. Warum das aber nicht in einem Aufwasch direkt bei der
Deklaration ( sprich: volatile char hour=13) geht weiss ich bis jetzt
noch nicht. Also falls jemand eine logische Erklärung hat. Immer her
damit. Ansonsten vielen Dank für eure Antworten.

Mfg  Bartman
Gast #78004
Lesenswert?

typedef unsigned char  u08;
u08 volatile empfangir = 0xff;
geht bei einem Projekt von mir wunderbar (erst char, dann volatile).

Habs jetzt auch geschafft, mal under linux zu comilieren. Ich bekomm
aber  nur alte rpm Pakete installiert, so dass ein Prog 32Byte größer
als mit Winavr wurde -> hätte nicht mehr in den AVR gepasst :-|
Gast #78005
Lesenswert?

> Das ist falsch. Volatile verhindert, dass der Compiler beim
> Optimieren die Variable anfasst.  In obigem Beispiel wird sie also
> gar nicht erst angelegt.

So wie ich diese Aussage lese, ist es schlicht Unsinn.

`volatile' verhindert jegliche Zugriffsoptimierungen auf eine derart
deklarierte Variable.  Jegliche Leseoperation von dieser Variablen
liest also vom entsprechenden RAM, jegliche Schreiboperation schreibt
dorthin.

Das ist die FAQ #1, bitte die FAQ auch lesen...

,,Angelegt'' (im Sinne von: Speicher reserviert) wird die Variable
sowohl mit als auch ohne volatile.
Gast #78006
Lesenswert?

puhh
ich such schon den ganzen tag nach einem fehler
...
wollte auch ne globale variable im interrupt ändern und dann woanders
auslesen..

jetzt mit dem volatile klappts endlich

und ich such mich hier kaputt

thx!!

lob ans forum

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