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
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]).
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
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
> 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); |
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
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
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.
Mit uint16_t kommt er aber nicht auf eine negative Zahl. Diese wird aber benötigt um die Scheilfen zu verlassen :)
> 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?
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).
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.