mikrocontroller.net

Forum: Compiler & IDEs 3 while-Schleifen zuviel für mega16???


Autor: Dominik L (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Ich bin absolut verwirrt. Warum macht mein Controller bei den
einfachsten Programmen nur Unsinn? Das Programm im Anhang soll mir
eigentlich nur 3 verschiedenen Zustände im Wechsel an PortB ausgeben,
bleibt jedoch nach dem dritten Zustand einfach stehen, also gibt 0x81
aus. Woran kann das liegen?
Habe noch ein paar mehr Beispiele, die noch kurioser sind. Die kann ich
später mal posten.

MFG Dominik

Autor: Christoph __ (chris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vermutlich gibt das Programm 3 verschiedene Zustände im Wechsel an PortB
aus. Also eigentlich genau das, was es soll. Vermutlich aber so schnell,
dass du das mit LEDs nicht sichtbar machen kannst.
Falls du das nicht beabsichtigt haben solltest:

Der gcc sieht wohl, dass deine while-Schleifen "sinnlos" sind und
ersetzt sie durch ein "a = 0;". Wenn du Warteschleifen willst, würd
ich dir delay.h aus der avrlibc empfehlen. Dann kannst du sicher sein,
dass zumindest das funktioniert (aber bitte die Doku lesen wegen der
Beschränkungen). Ansonsten musst du in die Schleifen irgendeinen
assembler-Befehl wie z.B. nop schreiben (wird nicht optimiert) oder du
deklarierst a als volatile (was aber andere Performance-Nebeneffekte
haben könnte, weswegen delay.h IMHO die bessere Wahl wäre [abgesehen
von Timern, aber du willst ja erstmal Warteschleifen]).

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey Chris.
Besten Dank! Das war es anscheined. Hat mir echt geholfen. Gibt es auch
Funktionen, die noch längere Wartezeiten ermöglichen als die 65000 Takte
mit dem 16 Bit Zähler?

MFG Dominik

Autor: Helge Dietert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

der Compiler optimiert die While-Schleifen wahrscheinlich komplett weg,
da sie für ihn keinen Sinnn ergeben, d.h. entweder die speziellen
Bibliotheksfunktionen verwenden oder so was selbst schreiben. Jenes ist
wahrscheinlich portabler und zuverlässiger.

Der Prozesser schaltet wahrscheinlich die drei Zustände durch und macht
dann den Rücksprung, der immerhin 2-Takte braucht, so dass du nur das
wahrnimmst. Schau Dir das Assembler mal an!

Helge

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

Bewertung
0 lesenswert
nicht lesenswert
> Gibt es auch Funktionen, die noch längere Wartezeiten ermöglichen
> als die 65000 Takte mit dem 16 Bit Zähler?

Hier verwechselst du wohl gleich mal alles Mögliche.

Erstens, mit einem 16-bit-Zähler kann man sehr viel mehr als nur 64
Ki Takte zählen, da man ihn noch mit einem Vorteiler versehen kann,
der bis zu 1:1024 teilt, das macht also maximal 64 Mi Takte bis zum
Überlauf mittels Hardware.  Dann kann man natürlich noch den Overflow-
Interrupt auswerten, und softwaremäßig N weitere Bytes ,,nach oben''
zur Zählweite hinzufügen.

Zweitens, die Funktionen in <avr/delay.h> gestatten zwar auch nur 64
Ki als maximales Argument (in _delay_loop_2), aber das teilt sich auch
nochmals durch 4 Takte pro Schleifendurchlauf, also 256 Ki Takte
maximal.  Die kann man natürlich noch einfach schachteln:
#include <stdint.h>

#define F_CPU 8000000UL
#include <avr/delay.h>


...
uint8_t i;
...
/* 1 Sekunde warten */
for (i = 0; i < 100; i++)
  _delay_ms(10);

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg.
Du hast natürlich recht :-) Hab net wirklich nachgedacht... Also danke
dass du mir mal eben die Augen geöffnet hast.

Grüße Dominik

Autor: michi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

@Christoph

warum sind diese drei while schleifen denn sinnlos?

void main(void){
  int16_t a;
  int16_t h=2;
  DDRB=0xff;
  while(1){
    a=30000;
    PORTB=0x0f;

    while(a>0){
      a--;
    }
    a=30000;
    PORTB=0xf0;

    while(a>0){
      a--;
    }
    PORTB=0x81;
    a=30000;

    while(a>0){
      a--;
    }
  }
}

Irgendwie machen dise schleifen doch sinn, oder?
Warum sollten die wegoptimiert werden.
Diese schleifen währen doch sinnlos:

while(a>0){}


cu

Autor: mthomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur vom kurz drueberschauen: Die Schleifen werden nicht gebraucht, da
a=0 ohne Schleifenkonstrukt bestimmt werden kann . Aber a wird nie
genutzt, also faellt "alles was damit zu tun hat" weg. Uebrig bleiben
die Portzuweisungen. Falls das ganze irgend eine Art Zeitverzoegerung
sein soll: volatile uint16_t a.

Autor: Thomas Kropf (thomas_k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit uint16_t kommt er aber nicht auf eine negative Zahl. Diese wird aber
benötigt um die Scheilfen zu verlassen :)

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Mit uint16_t kommt er aber nicht auf eine negative Zahl. Diese
> wird aber benötigt um die Scheilfen zu verlassen :)

Wie kommst du auf die Idee?

Autor: Thomas Kropf (thomas_k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uint bedeutet unsigned

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, und?
Ist '0' negativ?

Autor: ---- (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um weiteren Mißverständnissen vorzubeugen:

Der Hinweis ging an mthomas, da er aus "int16_t a" aus dem Original
(versehentlich) schnell ein "uint16_t a" gemacht hatte. Die
Folgerung, daß mit diesem Variablentypen die Schleife nicht
abgebrochen werden könne, war falsch...

@Patrick: Du weißt doch genau was gemeint war. Nicht auflaufen
lassen... da kriegste nur Schelte. *;-)*
Du hast zwar Recht, aber Thomas' Hinweis in der Grundidee war auch
gerechtfertigt - nur die Ausführung war mangelhaft ;-)

----, (QuadDash).

Autor: Patrick Dohmen (oldbug) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
'tschuldigung! Hab mich zu schnell hinreißen lassen :-)

Autor: Thomas Kropf (thomas_k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ups, tut mir echt Leid. Hab ich da gewaltig vertan :(

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.