www.mikrocontroller.net

Forum: Compiler & IDEs Mein erstes C-Programm - Wie funktioniert es ?


Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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;
}

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo da hab ich die Schleife her ;).

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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:
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.

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

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ;)

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, vielleicht hätte ich selbst mal die Doku nochmal genauer lesen 
sollen.
Auf http://www.nongnu.org/avr-libc/user-manual/group__... 
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?

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ;)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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
*****
  DDRD = 0xFF;

main.c
******
#include "abc.h"

int main()
{
}

Das kann nicht funktionieren, da ja nach der Textersetzung dieses
hier entsteht
  DDRD = 0xFF;

int main()
{
}

und somit die Zuweisung da ganz alleine in keiner Funktion steht
und sowas in C nicht erlaubt ist.

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: die ??? (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vor allem kann man auf dem PC sehr gut mit Pointern spielen und 
probieren. Die Debugger sind dort sehr komfortabel.


Karl heinz Buchegger wrote:

> oder
  while( 2 + 8 )
> oder
  while( 1 < 0 )  // ?
> ... Hauptsache der Teil in der Klammer wird nicht zu 0 ausgewertet.

Na na!  ;^)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die ??? wrote:

> oder
>   while( 1 < 0 )  // ?
> 
>> ... 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 :-)

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.