Hallo ich bin am verzweifeln. Wer kann mir helfen?
Ich habe versucht den Beispiel Quellcode aus dem Buch "AVR Hardware und
Programmierung in C" sd-karte.c mit dem AtmelStudio kompilieren. Zum
linken und brennen kommt es nicht. AtmelStudio bricht mit vielen
undefined reference to ....Fehlermeldungen ab.zb.
Error 28 ld returned 1 exit status collect2.exe 0 0 GccApplication8
Error 5 undefined reference to `fat_loadFatData' C:\Users\mb_win
7\Documents\Atmel
Studio\6.2\GccApplication8\GccApplication8\Debug/.././GccApplication8.c
120 1 GccApplication8
Error 26 undefined reference to `uputc' C:\Users\mb_win
7\Documents\Atmel
Studio\6.2\GccApplication8\GccApplication8\Debug/.././GccApplication8.c
146 1 GccApplication8
Error 2 undefined reference to `uputs' C:\Users\mb_win
7\Documents\Atmel
Studio\6.2\GccApplication8\GccApplication8\Debug/.././GccApplication8.c
110 1 GccApplication8
Error 19 undefined reference to `ffclose' C:\Users\mb_win
7\Documents\Atmel
Studio\6.2\GccApplication8\GccApplication8\Debug/.././GccApplication8.c
137 1 GccApplication8
...... ......
und noch einige mehr undefined reference to Fehlermeldungen andere
Fehlermeldungen außer der Error 28 ld returned 1 exit status und viele
undefined reference to und erscheinen nicht.
wer kann mir helfen? Liegt es daran das der Compiler einen Zugriff auf
der SD Karte sucht und nicht darauf zugreifen kann?
vielen Dank
Holger
code
Danke, Danke das Brennen auf den Atmega hat funktioniert.
mal sehen ob auf der SD Karte auch was zu lesen ist.
Noch eine dumme Frage warum müssen alle
*.c Dateien aus dem Beispiel im AVR Studio
zum Projekt hinzu? Ich dachte mit den Header Dateien *.h ist alles
erledigt und alle nötigen Funktionen zum schreiben und lesen auf der
Karte sind dadurch im Projekt?
Holger
>Noch eine dumme Frage warum müssen alle>*.c Dateien aus dem Beispiel im AVR Studio>zum Projekt hinzu? Ich dachte mit den Header Dateien *.h ist alles>erledigt und alle nötigen Funktionen zum schreiben und lesen auf der>Karte sind dadurch im Projekt?
Header Dateien enthalten keine Funktionen. Sie sagen dem
Compiler nur wie Funktionen aufgerufen werden. Die
eigentliche Funktion steckt in der *.c Datei.
Wenn diese *.c nicht mit compiliert wird meckert
dann der Linker weil er die Funktion nicht finden kann
und meldet: undefined reference. Jedesmal wenn du also
undefined reference liest weisst du das du eine notwendige
*.c Datei nicht zum Projekt hinzugefügt hast. Oder eine
Library beim Linkeraufruf fehlt, aber das ist ein anderes Thema.
Hallo Holger,
hab ich nicht gleich erkannt du bist ja mein Namensvetter.
Super!! auf der SD Karte wurde die Datei Test.txt mit dem Inhalt
Hello world. File Size: 0 Bytes
Hello world. File Size: 33 Bytes
Hello world. File Size: 67 Bytes
geschrieben und konnte mit Windows gelesen werden.
nochmals Danke alleine wäre ich verzweifelt.
also muss ich dann bei jedem eigenen C Programm wenn ich die Funktionen
aus dem oben gezeigten Code zB. ffwrites ((uint8_t*)"Hello world.");
verwenden will immer alle Header Dateien *.h und alle *.c Datei aus dem
Beispiel mit einfügen.
Das mit der SD Karte ist schwieriger als ich dachte.
Zum Verständnis gibt es auch Header Dateien *.h mit Funktionen? und kann
ich die einzelnen *.c Datei Code in eine einzelne *.c Datei
zusammenführen oder besser nicht.
Holger
Hallo
noch eine Frage wer kann mir sagen, was das uint8_t* mit Stern in
ffwrites ((uint8_t*)"Hello world.")bedeutet und wie der Compiler im
Projekt die Reihenfolge im Programmablauf der verschiedenen .c Datei
Code erkennen kann, wenn im Projekt des AVR Studio mehrere c code
eingebunden sind?
Holger
Holger W. schrieb:> Hallo> noch eine Frage wer kann mir sagen, was das uint8_t* mit Stern in> ffwrites ((uint8_t*)"Hello world.")bedeutet und wie der Compiler im> Projekt die Reihenfolge im Programmablauf der verschiedenen .c Datei> Code erkennen kann, wenn im Projekt des AVR Studio mehrere c code> eingebunden sind?
Ein C-Buch...
Sorry wenn ich lese dass jemand ne SD-Karte nutzt, aber gleichzeitig
keine Ahnung von den fundamentalen Grundlagen seiner Programmiersprache
hat, da bekomm ich die Krätze.
Cyblord -. schrieb:> Ein C-Buch...>> Sorry wenn ich lese dass jemand ne SD-Karte nutzt, aber gleichzeitig> keine Ahnung von den fundamentalen Grundlagen seiner Programmiersprache> hat, da bekomm ich die Krätze.
Siehst Du: Mir geht's genau so, wenn ich Dein immer gleiches, saublödes
"von der Seite Annölen" in mindestens 10 Threads/Tag lesen soll.
Das hält man doch eigentlich im Kopf nicht aus...
Kai M. schrieb:> Cyblord -. schrieb:>> Ein C-Buch...>>>> Sorry wenn ich lese dass jemand ne SD-Karte nutzt, aber gleichzeitig>> keine Ahnung von den fundamentalen Grundlagen seiner Programmiersprache>> hat, da bekomm ich die Krätze.>> Siehst Du: Mir geht's genau so
Hilft lieber dem TE anstatt hier Offtopic zu nölen. Bei persönlichen
Problemen gibt's pn.
Du bist also nicht der Ansicht der TE sollte sich ein C-Buch gönnen?
Warum nicht? Denkst du so ist alles ok? Wenn du ihm nun von Pointern
erzählst und noch bisschen was über Funktionen. Dann läuft das? Los lass
mal was zum Thema hören. Nur einmal.
Cyblord -. schrieb:> Hilft lieber dem TE anstatt hier Offtopic zu nölen.
Ich kann ihm nicht helfen, weil ich "C" für eine Dreckssprache halte.
Du willst ihm nicht helfen, obwohl Du es könntest.
Weil ich nicht helfen kann, halte ich die Pfoten still. Weil Du Dich
abreagieren willst, tust Du das nicht, sondern textest den
Fragesteller mit sinnlosem Mist zu.
Fazit: Weder Deine noch meine Antwort halfen ihm -nur: Mein Text wäre
gar nicht geschrieben worden, wenn Du nicht Deinen Unsinn gepostet
hättest.
> Bei persönlichen Problemen gibt's pn.
Darauf lege ich nicht den geringsten Wert.
Danke Ja ich bin Änfänger.
zur ersten Frage ffwrites ((uint8_t*)"Hello world.")
Macht also (uint8_t*)"Hello world." ein ein Array vom Typ char als
Argument für die Funktion ffwrites? Oder was hat der Stern hier für eine
Aufgabe.
zu meiner zweiten Frage: Zu der Reihenfolge im Programmablauf könnte
jemand einen Satz verlieren. Sind die anderen c Code nur Bibliotheken in
denen nur die Funktionen definiert sind, die aufgerufen werden?
Ich habe zwei Bücher "C als erste Programmiersprache" und "C
Programmieren von Anfang an" In diesen Bücheren habe ich nichts dazu
gefunden, desshalb meine Fragen.
Das Buch "Grundkurs C von Jürgen Wolf" habe ich soeben bestellt.
Ich brauche hier keine ausführliche Beschreibung, nur einen Denkanstoß.
was mit dem Stern ist.
Danke Holger
@ Holger Weiß (mb_holger)
>Macht also (uint8_t*)"Hello world." ein ein Array vom Typ char als>Argument für die Funktion ffwrites? Oder was hat der Stern hier für eine>Aufgabe.
"Hello world." ist ein konstanter String, also ein Array aus chars.
Der Funktion ffwrites wird der ZEIGER auf dieses Array übergeben. Dieser
Zeiger ist vom Typ char* (Zeiger auf char)
(uint8_t*) ist ein Cast. D.h. der Zeiger auf char (char*) wird zum
Zeiger auf uint8_t (uint8_t*) umdeklariert. Technisch sind char und
uint8_t nahezu identisch, es ist ein einfaches Bytes. Aber C ist etwas
pingelig und nimmt es hier genau. Ohnde den Cast würde dein Compiler
eine Warnung erzeugen, weil ein falscher Zeigertyp an die Funktion
übergeben wird. Mit Cast kommt keine Warnung.
ich muß noch mal nerven zu ffwrites ((uint8_t*)"Hello world."). Sowei
habe ich alles verstanden. Der Funktion wird der Zeiger auf dem String
übergeben.
Ist der Klammeroperator um (uint8_t*) wegen der Priorität in dem
Ausdruck(uint8_t*)"Hello world.", aber bei zum Beispiel
ffwrites ((uint8_t*)str) ergibt es keinen Sinn wegen der Priorität. Also
warum ist (uint8_t*) in Klammern?
Danke Holger
(uint8_t*)"Hello world." hab ich verstanden.
"Hello world." ist ein Array aus chars. Wie kann eine unit8_t den
Speicherbereich des Array aus chars darstellen ? müßte der Zeiger auf
ein
Array nicht wenigstens auch ein Array sein?
Holger
Holger W. schrieb:> (uint8_t*)"Hello world." hab ich verstanden.>> "Hello world." ist ein Array aus chars. Wie kann eine unit8_t den> Speicherbereich des Array aus chars darstellen ? müßte der Zeiger auf> ein> Array nicht wenigstens auch ein Array sein?
Zeiger ist Zeiger.
Ein Zeiger ist einfach nur die Adresse im Speicher an der sich etwas
befindet.
Im Speicher stehen Bytes. Irgendwelche Bytes. Im Speicher gibt es keine
Markierung, was da an dieser Stelle steht. Da stehen einfach nur Bytes.
Was an einer Stelle im Speicher zu finden ist, das definiert sich durch
die Verwendung.
Wenn ich schreibe
1
inti=48;
(Annahme: 16 Bit int)
dann werden dafür im Speicher 2 Bytes reserviert und in diese beiden
Bytes werden die entsprechenden Bits so geschrieben, dass sich daraus
die int-Zahl 48 ergibt, WENN man diese beiden Bytes als int
interpretiert.
Ich muss sie aber nicht als int interpretieren. Das ich das tue, liegt
einzig und alleine daran, dass ich die Variable als int definiert habe,
so dass der Compiler davon ausgeht, dass wenn ich schreibe
1
k=2*i;
ich haben will, dass er von der Speicheradresse an der i zu liegen
kommt, ich 2 Bytes holen möchte, die als int interpretiert werden.
Das ist eine der Grundannahmen. Definiere ich irgendetwas von einem
Datentyp, dann möchte ich dieses auch genau in diesem Sinne verwendet
haben.
Das muss aber nicht so sein. Ich kann den Compiler auch überstimmen. Ich
kann sagen: Hey, ist mir doch scheiss egal, ob da die beiden Bytes im
Speicher eigentlich einen int formen, ich will jetzt, dass wir mal
kurzzeitig so tun, als ob da nur ein einzelnes Byte liegen würde - und
genau diesen einzelnen Bytewert will ich haben. Nimm also die Adresse
von diesem ominösen i, wo auch immer das im Speicher liegt, und dann tun
wir mal so, also ob an dieser Stelle zb ein uint8_t im Speicher liegen
würde (also 1 Byte) - und genau dieses Byte will ich haben.
1
*(uint8_t*)&i
Ich kann auch sagen: (Selbes Spielchen) Vergiss, dass dort im Speicher
ein int liegt. Ich will haben, dass du die Adresse an der i im Speicher
liegt so auffasst, als ob dort ein double im Speicher liegen würde. Hol
dir also die Anzahl an Bytes von dort aus dem Speicher, die für einen
double benötigt werden und tu so als ob das tatsächlich ein double wäre
1
*(double*)&i
oder ich kann ihm jeden anderen Datentyp (auch Strukturen oder Unions
oder Arrays oder Arrays von Strukturen) aufs Auge drücken. Und wenn ein
AVR keine Harvard Architektur hätte, dann könnte ich dem Compiler auch
dazu zwingen so zu tun, als ob an dieser Stelle im Speicher die
Maschinenbefehle einer Funktion zu finden sind, die aufgerufen werden
soll.
Und damit sind wir bei Casts und bei der Frage warum zum Teufel du noch
immer kein C Buch hast. Schön langsam sollte es doch auch dir dämmern,
dass es eine Unmenge an Kleinigkeiten gibt, die man wissen muss und ohne
deren Kentniss man nicht vernünftig ein Programm schreiben kann.
Holger W. schrieb:> Wie kann eine unit8_t den> Speicherbereich des Array aus chars darstellen ?
Wer sagt denn das?
Da steht
1
...(uint8_t*)....
und nicht
1
...(uint8_t)...
> müßte der Zeiger auf> ein> Array nicht wenigstens auch ein Array sein?
Ein Zeiger ist einfach nur eine Speicheradresse, die angibt an welcher
Stelle im Speicher etwas zu finden ist. Was dieses 'etwas' darstellt,
wird durch den beim Zeiger angegebenen Datentyp definiert. Hier
1
....(uint8_t*)....
wird halt ausgesagt: an dieser Stelle im Speicher liegt ein uint8_t. Und
da sich der Computer nicht wehren kann, wenn du den so erhaltenen Zeiger
einfach um 1 erhöhst, ist damit auch implizit enthalten: und an den
folgenden Speicherstellen liegen ebenfalls uint8_t, wenn man den
Zeigerwert entsprechend inkrementiert/erhöht. Datentypen ändern sich ja
nicht, wenn man die Werte inkrementiert. Erhöhe ich den Zeigerwert um 1,
dann hat der Zahlenwert der Adresse jetzt einen anderen Wert. Aber er
zeigt nach wie vor auf einen uint8_t, wenn er das vorher tat. Und das er
das tat, dafür hat ja der Datentyp (wenn auch mit einem Cast erzwungen)
schon gesorgt.
vielen Dank für eure Geduld,
ein Buch für Einsteiger habe ich damit komme ich nicht weiter. Ich habe
euren Rat befolgt und noch 2 Bücher bestellt.
Zu den Zeigern habe ich noch eine Unklarheit. Ein Zeiger beinhaltet eine
Adresse
im Speicher je nach Architektur zb. bei 32 bit beinhaltet eine Adresse
2 Byte? Viele Variablen oder Konstanten haben einen Adressbereich also
mehrere Byte. Wird durch den Datentyp im Zeiger der Adressbereich
bestimmt und ist der Zeiger immer die Adresse des ersten Bytes des
Bereiches der Variablen. Ist also ein Zeiger immer nur eine Adresse und
der Datentyp bestimmt die Anzahl der folgenden und somit den
Adressbereich?
Kann es durch einen Cast zu Überschneidungen oder Konflikten kommen zb.
bei globalen oder static ?
Holger
Holger W. schrieb:> ein Buch für Einsteiger habe ich damit komme ich nicht weiter.
Hm, merkwürdig. In dem Buch für Anfänger steht nix zu Zeiger und
Datentypen?
> Zu den Zeigern habe ich noch eine Unklarheit.> .. dies und das ..
Ja. Eine Variable (egal in welcher Programmiersprache) besteht aus
mehreren "Teilen":
einem Varaiablen-Namen: DonauDampfSchiffahrtsKapitänPatentNummer
einem Daten-Typ : integer
einem definierten Größe an Speicherplatz, welche so eine Variable
benötigt: (z.B. 2 bytes)
einem "lagerort" im Speicher (wen eine solche Variable existiert (z.B.
0xabcd
einen Wert, den solch eine Variable annehmen kann, z.B. 4711, oder
-0815, oder <null> (= uninitialisiert, kein definierter Wert)
dann gibts dann vielleicht noch ein weiteres Objekt, nämlich einem
Zeiger, der auf Objekte vom Typ xx(z.B. Integer) zeigt
(der Zeiger selbst hat natürlich auch wieder eine gewisse Größe, z.B. 2
bytes)
naja, und schließlich ist der Wert (Inhalt) des Zeigers gleich der
Speicheradresse auf das Objekt, auf das er zeigt.
in C ist der Stern '*' zu lesen als "Zeiger auf", und der '&' läßt sich
lesen als "Adresse von"
Wegstaben V. schrieb:> (der Zeiger selbst hat natürlich auch wieder eine gewisse Größe, z.B. 2> bytes
ja, das ist mir alles klar. ich hatte nur die spezielle Frage zur Größe
des Zeigers bzw dessen Adressbereich.
Ein Zeiger beinhaltet eine Adresse.
im Speicher je nach Architektur zb. bei 32 bit beinhaltet eine Adresse
2 Byte. Viele Variablen oder Konstanten haben einen Adressbereich also
mehrere Byte. Wird durch den Datentyp im Zeiger der Adressbereich
bestimmt und ist der Zeiger immer die 1.Adresse des
Bereiches der Variablen. Ist also ein Zeiger immer nur eine Adresse und
der Datentyp bestimmt die Anzahl der folgenden und somit den
Adressbereich?
Kann es durch einen Cast zu Überschneidungen oder Konflikten kommen zb.
bei globalen oder static ?
Beispiel:
Ein long int aus den Bytes an den Adressen 100, 101, 102 und 103 hat die
Adresse 100.
Ein direkt benachbartes long int hat die Adresse 104 (Bytes 104, 105,
106, 107).
Wird durch den Datentyp im Zeiger der Adressbereich
bestimmt und ist der Zeiger immer die 1.Adresse des
Bereiches der Variablen. Ist also ein Zeiger immer nur eine Adresse und
der Datentyp bestimmt die Anzahl der folgenden und somit den
Adressbereich?
Ein Zeiger zeigt auf eine Adresse(32bit System 4 Byte) oder nur auf ein
Byte?
Kann es durch einen Cast zu Überschneidungen oder Konflikten kommen zb.
bei globalen oder static ?
Danke Holger
Holger W. schrieb:> Wegstaben V. schrieb:>> (der Zeiger selbst hat natürlich auch wieder eine gewisse Größe, z.B. 2>> bytes>> ja, das ist mir alles klar. ich hatte nur die spezielle Frage zur Größe> des Zeigers
Die Größe des Zeigers selbst ist durch die Architektur definiert und
wieviel Speicher in dieser Architektur überhaupt adressierbar ist. Ist
die Architektur so, dass die Hardware nicht mehr als 64kByte mximal
hergibt, dann werden die Adressen wohl so bemessen sein, dass damit alle
überhaupt vorkommenden Adressen damit abgebildet werden können. Bei 64kB
sind das 2 Bytes. Kann eine Hardware mehr adressieren, dann werden auch
Adressen (und damit Zeiger Variablen, die ja Adressen Speichern können
müssen) auch entsprechend größer sein.
Du bemisst ja den Platz auf einem Briefkuvert auch danach, welches die
längste vorkommende Adresse sein wird.
(Um die Sache nicht zu verkomplizieren, lass ich jetzt erst mal
segmentierte Architekturen aussen vor)
> bzw dessen Adressbereich.
Wie gross das Objekt ist, auf das mittels eines Zeigers verwiesen wird,
das ist deswegen bekannt, weil man ja nicht einfach nur definiert, dass
man eine Zeiger Variable hat
1
zeigerMeinZeiger;
sondern weil man ja definiert
1
int*MeinZeiger;
dass dieser Zeiger auf einen int zeigt, oder das
1
double*MeinZeiger;
dieser Zeiger auf einen double zeigt, oder dass
1
structirgendeineStruktur*MeinZeiger;
dieser Zeiger auf ein Objekt vom Typ 'struct irrgendeineStruktur' zeigt.
In allen Fällen ist damit bekannt, wie gross der 'Adressbereich' dessen
ist, worauf der Zeiger zeigt.
> Ein Zeiger beinhaltet eine Adresse.> im Speicher je nach Architektur zb. bei 32 bit beinhaltet eine Adresse> 2 Byte.
Kann sein, kann auch nicht sein. Mit 32 Bit hat das erst mal nichts zu
tun, sondern damit, wie gross der vom Prozessor bearbeitbare Adressraum
überhaupt ist.
WEnn du wissen willst, wie gross bei dir konkret ein Zeiger ist, warum
fragst du dann nicht einfach deinen Compiler? Der weiss das.
1
intmain()
2
{
3
printf("%lu\n",(unsignedlong)sizeof(void*));
4
}
> Bereiches der Variablen. Ist also ein Zeiger immer nur eine Adresse und> der Datentyp bestimmt die Anzahl der folgenden und somit den> Adressbereich?
genauso ist es.
Bytes im Speicher haben kein Mascherl.
> Kann es durch einen Cast zu Überschneidungen oder Konflikten kommen zb.> bei globalen oder static ?
Natürlich.
Mit einem Cast kannst du alles anstellen, weil du effektiv jegliche
Datentypprüfung des Compilers damit abschaltest. Mit einem Cast
übernimmst du selbst die Verantwortung, das alles in Ordnung ist.