Guten morgen zusammen,
Ich hab gestern mal mein erstes C-Programm zusammen geschustert und es
funktioniert eigentlich auch. Aber ich hab eine Frage zu meinem eingenem
Programm ;)
ich verwende dort eine While Schleife "while(1)" wann ist diese schleife
erfüllt? Was muss "1" werden damit diese erfüllt wird ?
Momenten sieht es auf dem ATmega 32 so aus das die 4 LEDs der reihe nach
an und wieder ausgehen.
wäre die Programmier schreibweise ok oder geht das auch anders ?
Ich habe bis jetzt nur mit Assambler gearbeitet.
wäre cool wenn mir da jmd helfen könnte
int main (void)
{
DDRB = 0x00;
PORTB = 0xff;
DDRD = 0xf0; //PD0:PD3 Input PD4:PD7 Output.
PORTD = 0xf0; //int. Pullup für PD4:PD7 on.
while(1)
{
PORTD = 0x80; //PD7 = High - rote LED an
_delay_ms(500); //warte 500ms
PORTD = 0x00; //PD7 = Low - rote LED aus
_delay_ms(250); //warte 500ms
PORTD = 0x40; //PD6 = High - orange LED an
_delay_ms(500); //warte 500ms
PORTD = 0x00; //PD6 = Low - orange LED aus
_delay_ms(250); //warte 500ms
PORTD = 0x20; //PD5 = High - gelbe LED an
_delay_ms(500); //warte 500ms
PORTD = 0x00; //PD5 = Low - gelbe LED aus
_delay_ms(250); //warte 500ms
PORTD = 0x10; //PD4 = High - grüne LED an
_delay_ms(500); //warte 500ms
PORTD = 0x00; //PD4 = Low - grüne LED aus
_delay_ms(250); //warte 500ms
}
return 0;
}
Es ist eine Endlos-Schleife, die immer durchgeführt wird! Der Wert "1"
wird als logisch "True"/WAHR ausgewertet, die schleife also niemals
abgebrochen.
--> C-Grundlagen
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
Seb wrote:
> ich verwende dort eine While Schleife "while(1)" wann ist diese schleife> erfüllt?
immer
> Was muss "1" werden damit diese erfüllt wird ?
Nichts.
Der springende Punkt ist: Eine Bedingung ist in C auch nichts anderes
als ein 'arithmetischer Ausdruck', der ein Ergebnis liefert. Du musst
dir zb. i == 5 als Ausdruck vorstellen, der je nachdem ob die Bedingung
zutrifft entweder 1 (für wahr) oder 0 (für falsch) liefert.
while fordert keine Bedingung. Alles was das while will ist ein
'arithmetischer Ausdruck' der entweder 0 oder nicht 0 ist (1 ist
perfekt für 'nicht 0'). Und je nachdem ob das in der Klammer beim
while zu 0 oder nicht 0 wird, wird der Schleifenrumpf wiederholt.
1 ist perfekt für einen 'arithmetischen Ausdruck' der niemals 0
werden kann. Du hättest genausogut auch
while( 5 )
oder
while( 2 + 8 )
oder
while( 1 < 0 )
oder was auch immer schreiben können. Hauptsache der Teil in der
Klammer wird nicht zu 0 ausgewertet.
> wäre die Programmier schreibweise ok oder geht das auch anders ?
für dein erstes Programm ist das schon ok. Aber jetzt stell dir
mal vor, du müsstest 1024 LED ansteuern. Dann müsstest du den
prinzipiellen Programmteil
> PORTD = 0x80;> _delay_ms(500);> PORTD = 0x00;> _delay_ms(250);
immer wieder und immer wieder wiederholen. Wie gesagt im Prinzip
ist dieser Programmteil in all den 1024 Fällen immer gleich:
LED an einem Port einschalten
Warten
LED wieder ausschalten
Warten
Alles wodurch sich die 1024 Programmschnipsel unterscheiden sind
ein paar Zahlen (ok, und der Port, den lass ich mal ausser acht)
die angeben welche LED einzuschalten ist. Das ist aber perfekt
für eine Schleife, wenn es dir gelingt die Led-Steuer-Zahl aus
der Schleifenvariablen zu erzeugen.
Anstatt 1024 mal den praktisch gleichen Abschnitt zu haben, hast
du dann diesen Abschnitt nur 1 mal plus eine Schleifensteuerung
plus einer Formel die aus der Schleifenvariablen die Steuerzahl
für die LED generiert.
> ich verwende dort eine While Schleife "while(1)" wann ist diese> schleife erfüllt? Was muss "1" werden damit diese erfüllt wird ?
1 muß ungleich 0 sein, damit die Bedingung erfüllt ist. Eine andere Art,
eine Endlosschleife zu schreiben, ist for(;;). Da muß man nicht extra
eine eigentlich unsinnige Bedingung reinschreiben.
Zur Schreibweise des Programms:
Zunächst mal fehlen da verschiedene Sachen vor main(). Da du schreibst,
daß das Programm schon läuft, nehme ich an, daß du nur vergessen hast,
die mitzuposten.
> PORTD = 0x80; //PD7 = High - rote LED an
Man könnte auch schreiben:
1
PORTD=(1<<PD7);
> _delay_ms(500); //warte 500ms
Entweder läuft dein AVR mit ziemlich niedrigem Takt (500 kHz oder
weniger), oder du hast die Doku nicht gelesen. In letzterem Fall stimmt
das Delay halt nicht.
Rolf Magnus wrote:
>> _delay_ms(500); //warte 500ms>> Entweder läuft dein AVR mit ziemlich niedrigem Takt (500 kHz oder> weniger), oder du hast die Doku nicht gelesen. In letzterem Fall stimmt> das Delay halt nicht.
Mittlerweile sind auch längere Zeiten als 262 ms / F_CPU/MHz möglich.
Die werden dann als Schleife mit je 100 µs Durchlaufzeit emuliert.
Also ich habe das in der delay.h so verstanden das ich einfach nur den
µC Takt mit " #define F_CPU 400000UL " definiere und das fließt dann
einfach in die "berechnung" mit ein. ich hab auch mit dem oszi nach
gemessen und messe ca 500ms eher ein bisschen mehr so 510ms aber dat is
ja wurscht
@ Karl heinz Danke für die erklärung - hat mir sehr geholfen. ich teste
mal ein bisschen weiter ;)
Ok, vielleicht hätte ich selbst mal die Doku nochmal genauer lesen
sollen.
Auf http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html
steht zwar immer noch "The maximal possible delay is 262.14 ms / F_CPU
in MHz.", aber danach wird diese Aussage dann gleich revidiert.
> ich hab auch mit dem oszi nach gemessen und messe ca 500ms eher ein> bisschen mehr so 510ms aber dat is ja wurscht
Falls du mit dem R/C-Oszillator arbeitest, könnte das durch dessen
Ungenauigkeit kommen. Ansonsten: Optimierungen nicht an?
Also ich habe erst gestern mit der C-Programmierung angefangen mit den
verschiedenen Optimierungs-graden habe ich mich noch nicht auseinander
gesetzt.
Aber ich möchte jetzt erstmal testen was das mit den Header dateien auf
sich hat. Das habe ich nämlich aus dem tutorial noch nicht verstanden.
Also so wie ich das aufgefasst habe ist meine, ich sag mal "Main.c" mein
Hauptprogramm.
In meinem Hauptprogramm hab ich ja zum Beispeich mit:
"
DDRB = 0x00;
PORTB = 0xff;
DDRD = 0xf0; //PD0:PD3 Input PD4:PD7 Output.
PORTD = 0xf0; //int. Pullup für PD4:PD7 on.
"
Die Port Eingangs und Ausgangs richtung definiert wie auch in internen
Pull Ups. Könnte ich dann, um mein Hauptporgramm übersichtlicher zu
gestalten, die Power definition in eine extra Header Datei "port.h"
einfügen so das diese nicht mehr in der Main.c steht sondern nur noch in
der port.h file ?
Weil das hab ich nicht ganz verstanden wie man dann eine Datei einfügt
so das diese auch "eingebunden" wird ?!
Aus anderen Programmen habe ich zum beispiel gesehn das da zum beispiel
stand im "Main.c"
#include "vario_scp1000.h"
und in der "vario_scp1000.h" stand dann:
"
#ifndef __vario_scp1000_H
#define __vario_scp1000_H
Programm
Programm
Programm
etc...
#endif
"
Wenn ich das so bei mir schreibe:
"
// Port-Zuweisungen für den ATmega 32
#ifndef __Port_Zuweisung_H
#define __Port_Zuweisung_H
DDRB = 0x00;
PORTB = 0xff;
DDRD = 0xf0; //PD0:PD3 Input PD4:PD7 Output.
PORTD = 0xf0; //int. Pullup für PD4:PD7 on.
#endif
"
Wird mir für Zeile 6 bis 9 die Fehler meldung:
../Port_Zuweisung.h:6: error: expected identifier or '(' before
'volatile'
angezeigt.
Klärt mich bitte auf g. Im Tutorial hab ich nämlich garnichts darüber
gefunden wie das so alles aufgebaut ist und warum das so ist und in
welchem Zusammenhang *.h und *.c zueinander stehn.
Oh mein gott war das viel text ;)
Das Tutorial hier hat so seine Tücken.
Vor allen Dingen ist es kein Tutorial über C sondern ein
Tutorial über die Besonderheiten, die zum normalen standardisierten
C hinzukommen, wenn man einen AVR-µC programmieren will.
Zum Lernen von C ist es denkbar ungeeignet. Eigentlich setzt
dieses Tuturial schon ein gewisses Grundwissen in C vorraus.
Wenn du dich also erst mal in C einarbeiten musst, dann würde
ich dir empfehlen
* das nicht auf einem µC zu machen, sondern dir einen kostenlosen
Compiler für Windows zu besorgen und dort deine ersten
Schritte in C zu machen.
Dies vor allem deshalb weil man auf einem PC wesentlich bessere
Möglichkeiten zur Fehlersuche hat und auch ein funktioniertendes
Ausgabesystem von Anfang an zur Verfügung steht, auf dem man
mal Texte ausgeben lassen kann
* nicht unbedingt mit einem Tutorial den Einstieg zu machen, sondern
dir ein vernünftiges Buch zuzulegen. Nur ganz wenige Tutorien sind,
wenn überhaupt, so ausführlich wie ein Buch an dem der Autor
mindestens 1 Jahr lang gefeilt hat und dass von vielen Leuten
Korrektur gelesen wurde.
Ein #include ist im Grunde nichts anderes als die Anweisung an
den Preprozessor an dieser Stelle den Text aus einer anderen
Datei einzusetzen.
Der Präprozessor macht also nichts anderes als die Zeile
#include "irgendwas"
mit dem Inhalt der Datei "irgendwas" zu ersetzen.
Erst danach geht der so modifizierte Quelltext an den eigentlichen
Compiler.
Du musst also dafür sorgen, dass dieser Quelltext nach der Ersetzung
immer noch ein gültiges C Programm ist
abc.h
*****
1
DDRD=0xFF;
main.c
******
1
#include"abc.h"
2
3
intmain()
4
{
5
}
Das kann nicht funktionieren, da ja nach der Textersetzung dieses
hier entsteht
1
DDRD=0xFF;
2
3
intmain()
4
{
5
}
und somit die Zuweisung da ganz alleine in keiner Funktion steht
und sowas in C nicht erlaubt ist.
Mhm also ich hab hier 2 Bücher über C Programmierung liegen und ich hab
auch so die ersten 30 seiten gelesen. Ich habe dann natürlich auch die
ersten paar sachen in einem Windows C Compiler ausprobiert z.b. "printf"
oder rechen operationen mit Ausgabe. Aber ich fand das irgendwie komisch
weil printf werde ich doch bei der µC programmierung nie wieder
verwenden.
deswegen hatte ich fuer mich gesagt das die die PC "C" programmierung
sein lasse und direkt zu den µC gehe und das dort lerne.
Weil ich hatte dann auch in dem Buch ein bisschen rumgeblättert und da
waren so viele Befehle wo ich mir schon gedacht hab das ich diese
niemals bei der µC programmierung brauchen werden.
Meinste echt das ich erstma das Buch durcharbeiten sollte und dann mit
der µC programmierung in C anfangen sollte ?
Seb wrote:
> Mhm also ich hab hier 2 Bücher über C Programmierung liegen und ich hab> auch so die ersten 30 seiten gelesen. Ich habe dann natürlich auch die> ersten paar sachen in einem Windows C Compiler ausprobiert z.b. "printf"> oder rechen operationen mit Ausgabe. Aber ich fand das irgendwie komisch> weil printf werde ich doch bei der µC programmierung nie wieder> verwenden.
Das würde ich so nicht sagen.
printf kann man einsetzen (wenn man weiss wie man die Ausgabe des
Standard Audgabe Systems zb. auf eine UART umleiten kann).
Selbst wenn printf nicht direkt benutzt wird, so kann seine Cousine
sprintf dann doch ein nützliches Werkzeug sein, wenn es darum geht
bestimmte Formatierungen einer Ausgabe zb auf ein LCD zu erreichen.
> Weil ich hatte dann auch in dem Buch ein bisschen rumgeblättert und da> waren so viele Befehle wo ich mir schon gedacht hab das ich diese> niemals bei der µC programmierung brauchen werden.
Doch, die brauchst du alle. OK. malloc()/free() kommt auf einem µC
eher selten vor und alles was mit Dateihandling zu tun hat wird
auch eher selten bis gar nicht gebraucht, aber der Rest: Ist alles
für eine vernünftige µC Programmierung letztendlich notwendig.
Ganz im Gegenteil. Auf einem µC kommen dann noch Dinge dazu, die
ohne Basiswissen für immer unverständlich bleiben.
Und dann gibt es natürlich noch den weiten Bereich der 'Standard-
Verfahren', die sich nicht auf einzelne Befehle oder Funktionen
festmachen lassen, sondern die auf dem Verständnis von Prinzipien
beruhen. Arbeiten mit Arrays bzw. deren Spezialisierung für
Stringverarbeitung fallen mir da zb. spontan ein.
> Meinste echt das ich erstma das Buch durcharbeiten sollte und dann mit> der µC programmierung in C anfangen sollte ?
Das Buch zumindest teilweise auf einem PC durcharbeiten. Ich geh
mal davon aus, dass dein Buch am Ende eines jeden Kapitels
Übungsaufgaben hat. Die sind normalerweise eine gute Leitlinie.
Irgendwann wird es in dem Buch um Dinge wie Dateiverarbeitung bzw.
dynamische Speicherverwaltung gehen. Das sind Dinge, die auf einem
µC in der Leistungklasse wie einem MegaXX erst mal keine Rolle
spielen. Aber bis dorthin gibt es ein weites Feld von Dingen,
die man erst mal durcharbeiten soll (zb. String-verarbeitung)
und bei denen man mit LED-leuchtet/LED-leuchtet-nicht nicht wirklich
gut nachvollziehen kann, was da abgeht bzw. wo der Fehler steckt.
Das geht auf einem PC erst mal um Größenordnungen besser.
>> ... Hauptsache der Teil in der Klammer wird nicht zu 0 ausgewertet.>> Na na! ;^)
Zu meiner Verteidigung: Das war noch vor dem ersten Kaffee!
Ist ja schon gut, ich geh ja schon in die Ecke zum schämen :-)