3 while-Schleifen zuviel für mega16???

Gast #237997
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
Angehängte Dateien:
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]).
Gast
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
Gast
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
Moderator Persönliche Seite
> 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:
1
#include <stdint.h>
2

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

6

7
...
8
uint8_t i;
9
...
10
/* 1 Sekunde warten */
11
for (i = 0; i < 100; i++)
12
  _delay_ms(10);
Gast
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
Gast
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
Gast
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.
Gast
> 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?
Gast
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).

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 21 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.