www.mikrocontroller.net

Forum: Compiler & IDEs probleme mit globaler variable / interrupt


Autor: tubbu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi, ich habe eine Variable, die ich in einem Interrupt verwenden will,
die aber auch global verfügbar sein soll.

Ich deklariere die variable mit volatile in einem File data.c  und mit
extern in einem file data.h, das ich dann include.

Dennoch wird die variable bei jedem aufruf der Interruptroutine
resettet.

Was mache ich falsch?

Danke

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich deklariere die variable mit volatile in einem File data.c und
> mit extern in einem file data.h, das ich dann include.

Lass mich raten: bei "extern" hast du kein "volatile" davor, ja?

> Was mache ich falsch?

Genau das.  Überleg' doch mal, wie ein Compiler arbeitet.
"volatile"
ist ein sogenannter type qualifier, er bestimmt also einen bestimmten
Typ näher.  In diesem Falle werden durch diese Bestimmung bestimmte
Zugriffe auf diese Variable nicht mehr optimiert.  Nun spiel' mal
Compiler:

data.h:
extern uint8_t x;

data.c:
#include "data.h"

volatile uint8_t x;

main.c:
#include "data.h"

int
main(void)
{
  /* ... */
  while (x == 0) {
  }
  /* ... */
  return 42;
}

Was sieht der Compiler nach dem Präprozessor?

data.i:
extern uint8_t x;

volatile uint8_t x;

Das erste ist eine Deklaration, das zweite eine Definition.
Eigentlich solltest du eine Compilerwarnung bekommen, da die
qualifiers zwischen beiden verschieden sind.

main.i:
extern uint8_t x;

int
main(void)
{
  /* ... */
  while (x == 0) {
  }
  /* ... */
  return 42;
}

main.i ist nun aber die Stelle, an der der Compiler tatsächlich auf x
zugreift und wissen muss, dass sie `volatile' ist.  Nur: er weiß es
nicht.  Woher auch?  Das Einzige, was er an dieser Stelle weiß ist,
dass sie vom Type uint8_t ist und dass es sie ,,irgendwo'' (wo
genau,
weiß erst der Linker) außerhalb des aktuellen Übersetzungsmoduls
(compilation unit) gibt.  Da er nicht weiß, dass sie eigentlich
volatile ist, wird er deren Wert aber am Beginn der while-Schleife
genau einmal einlesen und danach nie wieder.

Autor: tubbu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die ausführliche Antwort.

Ich habe scjon bevor ich gepostet habe alle möglichen kombinationen
durchprobiert.

Ursprünglich hatte ich

data.c:

volatile unsigned char a;

data.h

extern volatile unsigned char a;

ich habe mit dieser kombination gerade ein wenig rumprobiert

in der main.c:

a=1;
DisplayOutput(1);

while(1)
{
    if(a > 100)
        DisplayOutput(5)
}
.....
SIGNAL (SIG_OVERFLOW0){
a=200;
}

Das Ergebniss ist, dass sehr schnell nacheinander immer 5 und 1
ausgegeben werden, so als ob der Controller ständig resetten würde.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> so als ob der Controller ständig resetten würde.

Dann tut er das wohl.  Denk dran, dass ein Interrupt, der
keinen Vektor hat (oder einen, dessen Namen falsch geschrieben
ist), einen Software-Reset auslöst.

Autor: tubbu_der (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> so als ob der Controller ständig resetten würde.

>Dann tut er das wohl.  Denk dran, dass ein Interrupt, der
>keinen Vektor hat (oder einen, dessen Namen falsch geschrieben
>ist), einen Software-Reset auslöst.

Ja das war es, hab ich dann auch rausgefunden..

das waren jetzt ein paar stunden rumprobiere..wegen sowas


jedenfalls vielen dank

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dafuer vergisst Du das aber auch nie wieder :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.