www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Code tut nicht was er soll Kanns der Compiler sein?


Autor: lowPowerJunkie (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi Forum,

Ich habe hier so ein schickes kleines Problem.
Ich habe zum einen das Problem, dass ich glaube (ohne an den 
Compileroptimierungen zu spielen, Einstellung -0s) funktionieren 
regelmäßig meine delays nicht. Grund zu der Annahme: Meine startcheck() 
funktionier manchmal, aber nicht immer...
Als weiteres kommt eine ganz wilde Sache hinzu:
Wenn ich einen Portpin in der main toggeln lasse sehe ich am Pin nur 
rauschen, also nix.
Lasse ich ihn hingegen in der ISR toggeln funktioniert das.
(Und die Umschaltzeiten sollten gleich sein!)
Hab das im Code auch dokumentiert wo es funktioniert und wo nicht.

Ich hab mal meinen ganzen Code angehängt. Vielleicht schaut mal jemand 
rein und kann mir helfen.

Ach ja die Ausgangspannung wird sauber geregelt (auch bei 
laständerungen), was heißt mein PI-Regler funktioniert.

2 Ideen was es sein könnte habe ich:
- Irgendwas stimmt mit meinem statusregister nicht.
- Ein kleiner dummer tippfehler...

Bitte helft mir!

Btw:
Leider funktioniert der AVR-Simulator nicht ganz bei mir. Erstens hängt 
er sich regelmäßig auf, 2. sind 50% aller Bedingungen fälschlicherweise 
wahr (sollten aber falsch sein), sobald ich die Compileroptimierungen 
zulasse. Ohne meckert aber die delay.h

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> // globales Statusregister
> uint8_t status = 0;
          ^- als volatile deklarieren

> status &= !(1<<TIMER_BIT);
            ^- das tut nicht das, was es dem augenschein nach tun soll
               '~' regelt

..weiter hab ich mich nicht vorgetraut

HTH und HF

Autor: Marcus Overhagen (marcus6100)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

// globales Statusregister
uint8_t status = 0;

änder das mal in

volatile uint8_t status = 0;

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
 uint8_t status = 0; 
Ein Klassiker: such mal hier im Forum nach "+Interrupt +volatile"
Wenn du den status nicht volatile machst, dann wird der in der 
Hauptschleife nicht mehr eingelesen, sondern nur mit einem statischen 
Registerwert gearbeitet...
Deshalb wird sich status hier niemals ändern:
    while ( !( status & (1<<TIMER_BIT) ) )  // TIMER_BIT wird ungefähr jede ms in ISR gesetzt
      __asm("NOP");

Autor: lowPowerJunkie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh DANKE jungs (und medl(s)?) das volatile wars... mensch jetzt 
funktioniert mein Regler auch ungefähr doppelt so stabil.
Ja ok das kleine Ausrufezeichen... ist mir beim durchlesen um zu prüfen 
ob alles akzeptabel ankam dann ebenfalls aufgefallen ^^

Ich bin euch sooo Dankbar. Und dann auch noch so schnell die Antworten! 
Einfach klasse! Ihr habt mir den Abend gerettet!

PS: Scheinbar wird aber das statusregister noch einmal geschrieben, 
bevor er es sich kopiert. Denn die while durchlaufen hat er sicher. 
sonst wäre die Ausgangsspannung nicht so stabil gewesen. aber ist ja 
auch egal.

Nochmals 1000-Dank!

Autor: Marcus Overhagen (marcus6100)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Soweit hatte ich mich garnicht vorgetraut ;)

Noch zwei Anmerkungen. Das __asm("NOP"); kannst du weglassen,
da reicht ein einzelnes ;

Die Zugriffe auf das status byte sind nicht atomar. Vor
Manipulation im Hauptprogramm deshalb Interrupts sperren.

Sonst könnte es sein, das bei späteren Erweiterungen mit weiteren
bits ggf im Interrupt welche gesetzt werden, die aber im Hauptprogramm
überschrieben werden bevor sie ausgewertet werden.
Das passiert, falls der Interrupt zwischen lesen und zurückschreiben
des Wertes innerhalb von status &= !(1<<TIMER_BIT); oder ähnlichem 
auftritt.

Gruß
Marcus

Autor: lowPowerJunkie (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
eine Sache bleibt: Die Frequenz: hab ich mich verrechnet?
mit meinem Oszi (Made in Germany, ein HAMEG HM 512, vermutlich älter als 
ich) messe ich eine Schaltdauer von ungefähr 0,3ms pro toggle.
Errechnet hatte ich aber ungefähr 1ms...

Rechnung:
prescaler: 1
Takt: 9,6MHz
Counter-TOP: 255
Softwareteiler: 38
=> ( 1s / 9.600.000 )  255  38 = 0,0010...s

Fehler?! Wo?!
Mein Oszi kann doch nicht mittlerweile um Faktor 3 langsamer geworden 
sein?
Oder kann ein altes Oszi sowas?

Autor: Timo S. (kaffeetas)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo lowPowerJunkie,

ist der "Vernier" Regler vom Oszi am linken oder rechten Anschlag.
Die alten Oszis haben tw. eine sog. Dehnung bei deinem Model geht die 
zufällig bis Faktor 3.
Mit dem Finger an der Messpitze kann man gut die Netzfrequenz sehen. 
Hast du da 50Hz oder bist du auf Bahnfrequenz?

Grüße
 Timo

Autor: name (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Noch zwei Anmerkungen. Das __asm("NOP"); kannst du weglassen,
> da reicht ein einzelnes ;
>
> Die Zugriffe auf das status byte sind nicht atomar. Vor
> Manipulation im Hauptprogramm deshalb Interrupts sperren.

der erste tip ist klasse. Ich hab mir zwar schon länger gedacht dass er 
bei ";" ja nur ein NOP machen kann, aber gewusst hab ichs nicht. Danke.

Oh gott... mit dem atomar hab ich jatz aber kämpfen müssen... aber danke 
auch für diesen Tip. Ich werde es beherzigen.

Danke Marcus


@Timo:
Vernier? ich glaub ich muss mir das ding nochmal genauer anschauen... 
bis auf ein/aus/helligkeit, Fokus, Spannungsauswahll, frequenz, und 
niveau(was auch das immer ist) lösst sich irgendwie kein knopf mehr 
drehen. Irgendwie sind die Bomben fest, aber da ich nich weiß wozu die 
gut sind, hats mich nie gestört.
Wer grad zufälig ne anleitung dazu hat, kann ja gerne mal posten. wird 
aber langsam Offtopic.
Trotzdem DANKE für den Hinweis Timo.

Autor: Timo S. (kaffeetas)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: faustian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"Irgendwie sind die Bomben fest"

Besser als wenn sie locker sind.

"niveau"=Wahrscheinlich Triggerpegel...

Autor: klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> der erste tip ist klasse. Ich hab mir zwar schon länger gedacht dass er
> bei ";" ja nur ein NOP machen kann, aber gewusst hab ichs nicht. Danke.

Er macht da aber kein NOP draus. Wäre aber auch unsinnig/überflüssig. 
Mit "while(x);" erzeugt man lediglich eine Schleife mit leerem 
Anweisungsteil. Leer heißt leer, also auch kein "NOP". In diesem Fall 
wird direkt das Abprüfen der Bedingung wiederholt...


Gruss

Autor: horst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um auf deine eigentliche Frage zu kommen:
> Code tut nicht was er soll Kanns der Compiler sein?

Ja.
Wahrscheinlich ist es auch der Compiler. Normalerweise erzeugt er das 
Programm so, wie man es ihm sagt, und nicht so, wie er soll.
Die Fälle, in denen es anders ist, sind wirklich selten.

Autor: Phantomix Ximotnahp (phantomix) Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Selbst wenn ; zu NOP kompiliert würde, hätte dies der Programmierer so 
nicht explizit gesagt. Das heißt - Status des IC vor NOP == Status des 
IC nach NOP -> der Compiler optimiert es weg.

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.