Hallo, ich bin neu hier und das ist mein erster Beitrag. Ich habe ein Problem mit dem UART, ich habe auch die Suchfunktion benutz, habe allerdings keine Lösung gefunden. Es geht un UART. Das Senden funktioniert schon ganz gut, allerdings klappt das Empfangen nicht. Ich habe auch schon in Tutorial nachgeschaut, allerdings half mir das auch nicht weiter. Ich verwende den Mega32. Ich habe nun schon alles durchsucht, allerdings ist mir mein Fehler nicht aufgefallen. Ziel dieses Programms ist es, zu erst "Test" auszugeben und da nach 4, von Benutzer eingegebenen, Zeichen gleich darauf auch auszugeben. Es handelt sich natürlich nur um einen Test, denn dies ist mein erstes UART-Projekt. Über Antworten würde ichmich sehr freuen. Mit Bestem Dank utzer
In deinem Programm sind ein paar klassische Fehler enthalten. Bitte besorg dir Literatur zum Thema C-Programmierung. So wie du dir das vorstellst, funktioniert * Stringverarbeitung in C nicht * das Handling von lokalen Variablen / Funktionsparametern nicht Kurz: Du brauchst ein Array um Zeichen speichern zu können. Eine Speicherfläche! Ein Zeiger kann auf so eine Speicherfläche verweisen, aber er ist es selber nicht. Fang erst mal mit kleineren Brötchen an. 1 Zeichen empfangen und zurückschicken. Und erst dann gehst du daran einen kompletten String zu empfangen, den du in einem Array zwischenspeicherst.
Hallo, danke für Deine Antwort. Ich habe es nun auch geschaft, einzelne Zeichen zu senden. Was eine Array ist habe ich nun auch verstanden, allerdings verstehe ich das mit dem Zeiger(Pointer) noch nicht. Könnte mir das vielleicht jemand in "einfachen Worten" erklären? mfg utzer PS: Bitte entschuldigt die späte Antwort, aber ich bin Schüler(15) und hab viel um die Ohren.
Ein Pointer (Zeiger) ist eine Variable wie jede andere auch. Ihr Inhalt ist eine Speicheradresse. Ein int ist eine Variable, welche eine ganze Zahl enthält Ein double ist eine Variable, welche eine Gleitkommazahl enthält EIn Pointer ist eine Variable, welche eine Speicheradresse enthält. Das ist im Grunde schon fast alles :-) Allerdings muss man in C immer auch dazu sagen: Wenn ein Pointer eine Speicheradresse enthält, was finde ich dann genau an dieser Stelle im Speicher vor. Wenn ich also einen int-Pointer habe int* PtrA; dann enthält PtrA eine Adresse im Speicher. Schau ich genau an dieser Stelle im Speicher nach, dann finde ich dort einen int vor. Ein double Pointer double* PtrX; enthält dann folgerichtig eine Speicherstelle unter der ein double im Speicher abgelegt wurde, etc. etc. Nun zeigt so ein Pointer nicht von alleine auf irgendeine Speicherzelle, sondern das muss der Programmierer erst mal festlegen. Auch wird der int, auf den der Pointer zeigt, nicht einfach aus dem Nichts generiert, sondern irgendjemand muss im Speicher erst mal Platz für so einen int reservieren. Auch das macht so ein Pointer nicht eigenständig. zb so
1 | int main() |
2 | {
|
3 | int a = 5; // Platz für einen int wird geschaffen |
4 | |
5 | int* PtrA; // Platz für den Pointer wird geschaffen |
6 | |
7 | |
8 | PtrA = &a; // und jetzt wird der Pointer eingerichtet. Der Inhalt des |
9 | // Pointers ist die Speicheradresse von a
|
10 | }
|
Oder als Grafik ausgedrückt PtrA a +---------+ +----+ | o-------------------------->| 5 | +---------+ +----+ So wie a als Inhalt den Zahlenwert 5 hat, so hat PtrA als Inhalt die Speicheradresse von a. Ausgedrückt durch einen Pfeil von PtrA nach a. So ist das natürlich ein wenig witzlos, wenn man nicht mit dem Pointer auch arbeiten könnte. Wird der Pointer 'dereferenziert', so wird gedanklich dem Pfeil gefolgt und der angegebene Wert von der entsprechenden Speicherstelle geladen/geschrieben. Deshalb ist es auch notwendig, dass der verwiesene Datentyp Teil des Datentyps des Pointers ist ( ein int-Pointer zeigt auf einen int, ein double Pointer zeigt auf einen double etc.)
1 | int main() |
2 | {
|
3 | int a = 5; // Platz für einen int wird geschaffen |
4 | |
5 | int* PtrA; // Platz für den Pointer wird geschaffen |
6 | |
7 | |
8 | PtrA = &a; // und jetzt wird der Pointer eingerichtet. Der Inhalt des |
9 | // Pointers ist die Speicheradresse von a
|
10 | |
11 | *PtrA = 7; // lege die 7 dort ab, wohin der Pointer zeigt |
12 | }
|
PtrA a +---------+ +----+ | o-------------------------->| 7 | +---------+ +----+ oder umgekehrt:
1 | int main() |
2 | {
|
3 | int a = 5; // Platz für einen int wird geschaffen |
4 | int b = 0; |
5 | |
6 | int* PtrA; // Platz für den Pointer wird geschaffen |
7 | |
8 | |
9 | PtrA = &a; // und jetzt wird der Pointer eingerichtet. Der Inhalt des |
10 | // Pointers ist die Speicheradresse von a
|
11 | |
12 | *PtrA = 7; // lege die 7 dort ab, wohin der Pointer zeigt |
13 | |
14 | b = *Ptra; // hole den aktuellen Wert von dort, wohin der Pointer zeigt |
15 | // und speichere ihn in b ab
|
16 | }
|
PtrA a +---------+ +----+ | o-------------------------->| 7 | +---------+ +----+ b +----+ | 7 | +----+ Und jetzt kommen Arrays ins Spiel. Arrays sind in C so halbe Datentypen. Man kann ein Array zwar definieren und kann auch auf einzelne Elemente eines Arrays zugreifen, aber man kann zb nicht ein Array an eine Funktion übergeben. Allgemeiner kann man sagen: Immer dann, wenn der Name eines Arrays ohne Indizierung vorkommt (also nur der Name alleine), dann wird anstelle des Arrays an sich, die Adresse des ersten Arrayelements genommen. Und diese Adresse kann man wiederrum an eine Funktion übergeben, wobei sie innerhalb der Funktion in einer Pointervariablen aufgefangen wird und zur Verfügung steht.
1 | int main() |
2 | {
|
3 | int Werte[5]; |
4 | |
5 | Werte[0] = 1; |
6 | Werte[2] = 8; |
7 | }
|
Dies generiert erst mal das Array Werte +---+---+---+---+---+ | 1 | 8 | | | | +---+---+---+---+---+ Versucht man nun dieses Array an eine Funktion zu übergeben
1 | int main() |
2 | {
|
3 | int Werte[5]; |
4 | |
5 | Werte[0] = 1; |
6 | Werte[2] = 8; |
7 | |
8 | foo( Werte ); |
9 | }
|
so wird anstelle des Arrays, die Adresse des ersten Array Elements übergeben Werte +---+---+---+---+---+ | 1 | 8 | | | | +---+---+---+---+---+ ^ | | | und diese Adresse wiederrum, wird von der aufgerufenen Funktion in einer Pointer-Variablen empfangen, die der Funktion während ihrer Ausführung zur Verfügung steht (und nach Beendigung der Funktion wieder verschwindet)
1 | void foo( int* Passed ) |
2 | {
|
3 | ...
|
4 | }
|
5 | |
6 | int main() |
7 | {
|
8 | int Werte[5]; |
9 | |
10 | Werte[0] = 1; |
11 | Werte[2] = 8; |
12 | |
13 | foo( Werte ); |
14 | }
|
Werte +---+---+---+---+---+ | 1 | 8 | | | | +---+---+---+---+---+ ^ | Passed | +--------+ +-------------------o | +--------+ Die Funktion kann über diesen Pointer, auf den Inhalt des Arrays zugreifen und auch verändern
1 | void foo( int* Passed ) |
2 | {
|
3 | int k = *Passed; |
4 | }
|
Werte +---+---+---+---+---+ | 1 | 8 | | | | +---+---+---+---+---+ ^ | Passed k | +--------+ +---+ +-------------------o | | 1 | +--------+ +---+ Oder aber auch auf irgendein anderes Arrayelement, indem sie den übergebenen Pointer als Anfang benutzt und einfach angibt, auf das wievielte Element zugegriffen werden soll.
1 | void foo( int* Passed ) |
2 | {
|
3 | int k = *Passed; |
4 | |
5 | *( Passed + 2 ) = 4; |
6 | }
|
Werte +---+---+---+---+---+ | 1 | 8 | 4 | | | +---+---+---+---+---+ ^ | Passed k | +--------+ +---+ +-------------------o | | 1 | +--------+ +---+ Nun ist aber die Syntax *( Pointer + Offset ) eine ekelhafte. In C hat man dem Abhilfe geschaffen, indem man den Arrayzugriff mittels Index so definiert hat, dass *( Pointer + Offset ) identisch ist zu Pointer[ Offset ] anstelle von *( Pointer + 3 ) = 2 kann und wird man auch oft schreiben:
1 | void foo( int* Passed ) |
2 | {
|
3 | int k = *Passed; |
4 | |
5 | *( Passed + 2 ) = 4; |
6 | Passed[ 3 ] = 2; |
7 | }
|
Werte +---+---+---+---+---+ | 1 | 8 | 4 | 2 | | +---+---+---+---+---+ ^ | Passed k | +--------+ +---+ +-------------------o | | 1 | +--------+ +---+ Es gibt noch mehr über Pointer zu sagen und vor allen Dingen zu entdecken. Aber im Grunde folgt alles andere aus dem bisher Gesagten, auch wenn einem das so nicht bewusst ist. Daher: Literatur, Literatur, Literatur. Denn ich hab ehrlich gesagt auch keine Lust, dir hier all das was in einem vernünftigen Buch auf 30 oder mehr Seiten erklärt ist, in ein paar Positings nahezubringen.
Hallo, vielen Dank für Deine Antwort, jetzt wird mir so einiges klar.....:-) allerdings habe ich versucht, dies jetzt auf den Code zu übertragen, allerdings funktioniert es nicht....
1 | void gets() |
2 | {
|
3 | char* Buffer; |
4 | char Line[10]; |
5 | char NextChar; |
6 | int StringLen = 0; |
7 | Buffer = &Line; |
8 | NextChar = getc(); // Warte auf und empfange das nächste Zeichen (in der getc-Funktion) |
9 | |
10 | while(StringLen<=4) |
11 | {
|
12 | Buffer[StringLen] = NextChar; |
13 | StringLen=StringLen+1; |
14 | NextChar = getc(); |
15 | }
|
16 | |
17 | StringLen=StringLen+1; |
18 | Buffer[StringLen] = '\0'; |
19 | // Noch ein '\0' anhängen um einen Standard
|
20 | // C-String daraus zu machen
|
21 | |
22 | return Line; //Ich glaub hier liegt der Fehler.......:-( (Muss es "return *Buffer" heißen???) |
23 | }
|
Was mache ich falsch? Ich komme einfach nicht weiter..... mfg utzer
1 | /* globaler Zeilenpuffer +/
|
2 | char Line[10];
|
3 | |
4 | /* char *gets(), damit sowas:
|
5 | 'int i = atoi(gets(Line, 4), 10);'
|
6 | spaeter mal geht */
|
7 | char *gets(char *Buffer, int StringLen) |
8 | {
|
9 | /* static char Line[10];
|
10 | ginge auch, WENN du weisst wo der Unterschied liegt
|
11 | */
|
12 | int idx =0; |
13 | while (idx < StringLen) |
14 | {
|
15 | Buffer[idx] = getc(); |
16 | idx ++; |
17 | }
|
18 | Buffer[idx] = 0; // Noch ein '\0' anhängen um einen |
19 | // C-String daraus zu machen
|
20 | return Buffer; |
21 | }
|
22 | int main(void) |
23 | {
|
24 | //...
|
25 | gets(Line, 4); |
26 | // jetzt steht in 'Line' dein String
|
hth, Jörg
Doran Strehnisch wrote:
>
1 | >
|
2 | > void gets() |
3 | > { |
4 | > char* Buffer; |
5 | >
|
Es gibt in dieser Funktion, so wie sie jetzt ist, absolut keinen Grund mit Pointern um sich zu schmeissen
1 | > char Line[10]; |
2 | >
|
3 | > .... |
4 | >
|
5 | |
6 | > return Line; //Ich glaub hier liegt der Fehler.......:-( (Muss es |
7 | > "return *Buffer" heißen???) |
8 | > } |
9 | >
|
Wie kann diese Funktion etwas retournieren, wenn im Funktionskopf steht, dass diese Funktion void ist, also nichts zurückliefern wird? Achtung: Das ist jetzt eine falsche Lösung, komme nach dem Code gleich drauf zu sprechen.
1 | char* gets() |
2 | {
|
3 | char Line[10]; |
4 | char NextChar; |
5 | int StringLen = 0; |
6 | |
7 | NextChar = getc(); // Warte auf und empfange das nächste Zeichen (in der getc-Funktion) |
8 | |
9 | while(StringLen<=4) |
10 | {
|
11 | Line[StringLen] = NextChar; |
12 | StringLen=StringLen+1; |
13 | NextChar = getc(); |
14 | }
|
15 | |
16 | StringLen=StringLen+1; |
17 | Line[StringLen] = '\0'; |
18 | // Noch ein '\0' anhängen um einen Standard
|
19 | // C-String daraus zu machen
|
20 | |
21 | return Line; //Ich glaub hier liegt der Fehler.......:-( (Muss es "return *Buffer" heißen???) |
22 | }
|
Das würde jetzt erst mal logisch aussehen. Ds Problem. Du kannst Line nicht returnen. Erinnere dich: lokale Variablen werden zerstört, wenn eine Funktion zu Ende geht. Also wird Line mit Beendigung der Funktion gets zerstört. Gleichzeitig können Arrays aber auch nicht kopiert werden, es wird lediglich die Startadresse des Arrays an den Aufrufer übergeben. Damit hat aber der Aufrufer dann die Startadresse eines Arrays, welches nicht mehr existiert. In so einem Fall, muss der Aufrufer der Funktion das Arrays bereitstellen und es in die Funktion hinein übergeben. Die Funktion befüllt es dann mit Werten.
1 | void gets( char * Line ) |
2 | {
|
3 | char NextChar; |
4 | int StringLen = 0; |
5 | |
6 | NextChar = getc(); // Warte auf und empfange das nächste Zeichen (in der getc-Funktion) |
7 | |
8 | while(StringLen<=4) |
9 | {
|
10 | Line[StringLen] = NextChar; |
11 | StringLen=StringLen+1; |
12 | NextChar = getc(); |
13 | }
|
14 | |
15 | StringLen=StringLen+1; |
16 | Line[StringLen] = '\0'; |
17 | // Noch ein '\0' anhängen um einen Standard
|
18 | // C-String daraus zu machen
|
19 | |
20 | }
|
21 | |
22 | int main() |
23 | {
|
24 | char Eingabezeile[10]; |
25 | |
26 | gets( Eingabezeile ); |
27 | |
28 | ...
|
29 | }
|
Aufpassen muss man nur, dass das Array beim Aufrufer gross genug allokiert wird, damit gets nicht auf Elemente des Arrays zugreift, die nicht existieren. http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F
Hallo, vielen, vielen Dank, dass ihr euch die Mühe gemacht habt, mir das so genau und ausführlich zu erklären..... Es hat funktioniert - Danke :-) über glücklich -utzer
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.