Forum: Mikrocontroller und Digitale Elektronik C-Code für Datenempfang mit USART


von Christian K. (christiankarle)


Angehängte Dateien:

Lesenswert?

Sehr geehrte Community,

Ich versuche gerade ein Programm zu schreiben das 11 Bytes per USART 
empfangen kann und diese dann in uart_string speichern soll. Eine 2 
Variable
String_Counter sagt an welcher Stelle in uart_string ein bestimmtes Byte 
gespeichert wird. Wenn der uart_string vollständig empfangen wurde soll 
String_Complete auf 1 gesetzt werden. Und das Empfangen beendet werden.

Meine Fragen: Wird das Programm funktionieren ?
              Gibt es Fehler? Wenn ja, welche?


P.S: Ich bin Anfänger in C... bitte schreibt mir nur einfache Antworten 
damit ich sie verstehen und nachvollziehen kann :)

Vielen Dank für Eure Bemühungen,

Christian


Datei im Anhang :)

von Helmut L. (helmi1)


Lesenswert?

Warum initialisierst du in einer Schleife ständig den UART?

von Peter K. (peterka2000)


Lesenswert?

Ich hab mir den Code jetzt nicht weiter angeguckt, was mit aber sofort 
ins Auge bohrt, ist die Tatsache, das du in einer Dauerschleife den UART 
intialisierst, die Interrupts einschaltest und einen Takt wartest. Das 
ganze gehöhrt über die Schleife (außer vielleicht das Nop)

EDIT: Verdammt, zu langsam

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

naja, mehr oder weniger tut es schon was, folgende ist falsch oder 
ungüstig:

> #define UART_MAXSTRLEN 10

schon mal sehr gut, aber warum verwendest du es nicht und schreibst 
immer die 10 wieder hin?

> int main(void)
> {
>    while(true)
>    {
>    USART_Initialisieren();
>    sei();
>    asm("nop");
>    }
>}

die Initalisierung und das sei sollte nicht in der while schleife 
stehen. Das Nop braucht bauch niemand.

> ISR(USART_RX_vect)
> {
> volatile unsigned char Temp;
hier macht volatile keinen sinn, kann wegfallen

> Temp=UDR;
>
> if(String_Counter<=10&&String_Complete==0)
und den define nutzen und die Abfrage ist falsch es muss < 10 sein, 
sonst überschreibst du dir den speicher

>if(String_Counter==11)
>  {
>    String_Counter=0;
>    uart_string[10]=0;
du hast nur für 10 Elemente Platz uart_string[10] ist das 11.Element

von Oliver (Gast)


Lesenswert?

Das Nop kann ganz weg.

Ansonsten hast du den klassischen Anfängerfehler bei der Arraygröße 
gemacht. 11 Zeichen in ein Array der Größe 10 zu schreiben, geht schief.

Ansonsten erst einmal nicht schlecht. Aber jetzt geht es ja erst los, 
denn du willst ja bestimmt mit dem eingelesenen String was anstellen.

Oliver

von Christian K. (christiankarle)


Lesenswert?

Hallo,

danke für die vielen Antworten.
Ich habe das Programm noch einmal verbessert.

Datei im Anhang :)

Könnte jemand da noch einmal darüberschauen ob ich alle Fehler 
berichtigt habe ?


Hier im Forum gibt es wirklich tolle Leute.
Danke für Eure Unterstützung:)

von Peter II (Gast)


Lesenswert?

Christian Karle schrieb:
> Datei im Anhang :)

wo?

von Christian K. (christiankarle)


Angehängte Dateien:

Lesenswert?

Tut mir leid, habe sie vergessen anzuhängen :D
Hier ist sie :)

von Peter II (Gast)


Lesenswert?

noch nicht alles richtig:

> int main(void)
>{
>
>  UBRRL  = 1;
>  UBRRH  = 0;
>  UCSRC  = (1<<URSEL)|(3<<UCSZ0);
>  UCSRB  = (1<<RXCIE)|(1<<RXEN);

das war vorher besser, wenn es in einer extra Funktion steckt.

>    asm("nop");
macht das weg, das braucht niemand.

    }
}

> volatile unsigned char Temp;
volatile braucht hier auch niemand, wegmachen

>    uart_string[10]=0;
dein string ist nur 10 zeichen lang, du schreibt aber in das 11. rein !

von Karl H. (kbuchegg)


Lesenswert?

> uart_string[10]=0;

Immer noich falsch.

Dein Array ist 10 Elemente gross.
0, 1, 2, 3, 4, 5, 6, 7, 8, 9

zähl nach. Das sind 10 Stück. Das Element mit dem höchsten Index, hat 
den Index 9!

Bei der Definition gibst du die Anzahl an gewünschten Elementen an. Da 
wir aber bei 0 anfangen zu zählen, gibt es bei einem Array der Größe N, 
kein Element mit dem Index N.

Das letzte Element in deinem Array, erreichst du am einfachsten mit
1
    uart_string[UART_MAXSTRLEN-1] = '\0';

Schreib '\0' um das 0-Terminierungszeichen zu schreiben. Das ist zwar 
identisch zu 0, betont aber etwas mehr, dass du es hier mit 
Textverarbeitung zu tun hast, mit einem Zeichen.

: Bearbeitet durch User
von Christian K. (christiankarle)


Angehängte Dateien:

Lesenswert?

Ok, also dann so :)

von Peter II (Gast)


Lesenswert?

nö:

> sei();
das geht nicht, man kann kein code außerhalb einer Funktion schreiben


dein String hat keine keine 0 mehr am ende, bis jetzt stört das noch 
nicht. Die Frage ist was du später damit machen willst.

von Peter II (Gast)


Lesenswert?

UART_initialisieren

wird nicht aufgerufen

von Karl H. (kbuchegg)


Lesenswert?

Jetzt ist es kein String mehr.

Du MUSST als letztes gültiges Zeichen in deinem Array das Zeichen '\0' 
haben!
Das Array kann auch größer sein, als der String lang ist. Das '\0' 
Zeichen markiert, wo der String aufhört. Das ist in C so definiert. Alle 
String-verarbeitenden Funktionen verlassen sich drauf, dass sie dieses 
Zeichen dort vorfinden, wo der String tatsächlich aufhört. Ohne '\0' 
hast du ein Array mit Zeichen drinn. Aber du hast keinen String. 
Spätestens wenn du dann mit den str... Funktionen anfängst den String zu 
bearbeiten, kriegst du Probleme.

von Karl H. (kbuchegg)


Lesenswert?

Das letzte Element in deinem Array, erreichst du am einfachsten mit
1
    uart_string[UART_MAXSTRLEN-1] = '\0';
Dann passt dir der Compiler die Zuweisung wieder an deine Array-Grösse 
an.

Schreib '\0' um das 0-Terminierungszeichen zu schreiben. Das ist zwar 
identisch zu 0, betont aber etwas mehr, dass du es hier mit 
Textverarbeitung zu tun hast, mit einem Zeichen.

von Helmut L. (helmi1)


Lesenswert?

Das hier kann man kürzer schreiben:

uart_string[String_Counter]=Temp;
String_Counter++;

so:

uart_string[String_Counter++]=Temp;

von Karl H. (kbuchegg)


Lesenswert?

Ein Wort noch in Code strategischer Sache.

Sowas
1
if(String_Counter<UART_MAXSTRLEN&&String_Complete==0)
ist schlecht. Das ist eine Wurscht aus Buchstaben, bei der man erst mal 
15 Sekunden suchen muss, wo ein Wort aufhört und wo das andere anfängt.

Seit du 6 Jahre alt bist und in die Grundschule gegangen bist, hast du 
dein Gehirn daruf trainiert: Zwischen Wörtern sind Leerzeichen.

Das ist deinem Gehirn so vertraut geworden, dass es dir nicht mehr 
richtig bewusst ist. Merken tust du es 
erstdannwennmandiesesmalignoriertunddieWörterohneLeerzeichenaneinanderkl 
ebt.

Hast du gemerkt umwieviel schwieriger der letzte Satzteil zu lesen war?
Ja? Hast du es gemerkt? Offensichtlich ist das keine gute Idee.
Nur: Warum machst du es dann im Code?
Programmieren ist schon schwierig genug. Da muss man dem Leser nicht 
auch noch Prügel zwischen die Beine werfen
1
  if( String_Counter < UART_MAXSTRLEN &&
2
      String_Complete == 0 )

viel besser zu lesen!


Und achte auf deine Einrückungen! Konsistenz ist wichtig. Wenn du nach 
jeder öffnenden { um 2 Zeichen einrückst, dann musst du dieses Schema 
aber auch durchziehen!

von Christian K. (christiankarle)


Angehängte Dateien:

Lesenswert?

Also...ich habe das jetzt noch einmal überdacht...
Falls dieser Quelltext nun korrekt ist werden ja nun 10 Bytes 
gespeichert.
Wenn diese 10 Bytes dann gespeichert sind würde aber
uart_string[UART_MAXSTRLEN-1] = '\0'; doch das letzte Byte wieder 
löschen und stattdessen '\0' an die 10 Stelle schreiben? Oder sehe ich 
das falsch?

von Karl H. (kbuchegg)


Lesenswert?

Christian Karle schrieb:
> Also...ich habe das jetzt noch einmal überdacht...
> Falls dieser Quelltext nun korrekt ist werden ja nun 10 Bytes
> gespeichert.
> Wenn diese 10 Bytes dann gespeichert sind würde aber
> uart_string[UART_MAXSTRLEN-1] = '\0'; doch das letzte Byte wieder
> löschen und stattdessen '\0' an die 10 Stelle schreiben? Oder sehe ich
> das falsch?

Nein, das siehst du richtig.

Daher: Um einen String mit 5 darstellbaren zeichen speichern zu können, 
brauchst du ein Array das 6 chars groß ist. Ganz einfach.

Deine Strings sind 10 Zeichen lang, also muss das Array 11 chars groß 
sein.

: Bearbeitet durch User
von Christian K. (christiankarle)


Angehängte Dateien:

Lesenswert?

Ich habe nun um diesem Problem zu entgehen in
volatile char uart_string[UART_MAXSTRLEN+1];
eine 1 addiert.

Bedeutet mein String kann nun 11 Chars aufnehmen
(ist meine Formulierung richtig???)
Dann habe ich

uart_string[UART_MAXSTRLEN-1] = '\0';

zu:
uart_string[UART_MAXSTRLEN] = '\0';

geändert.

Somit würde ich ja meinem Problem entgehen, sehe ich das richtig?

von Karl H. (kbuchegg)


Lesenswert?

Die Überlegung ist soweit korrekt.

von Peter II (Gast)


Lesenswert?

Die frage ist ob du die Richtigen Daten empfängst. Was ist wenn du den 
µC erst einschaltet wenn schon Daten übertragen wurden? du ließt ja 
immer 10 Zeichen ohne das du wirklich weißt wo Anfang und ende ist.

Aber das kommt darauf an was du überhaupt machen willst.

von Christian K. (christiankarle)


Lesenswert?

Bedeutet dass, das mein Programm so wie es hier steht funktioniert ?

von Helmut L. (helmi1)


Lesenswert?

Christian Karle schrieb:
> Bedeutet dass, das mein Programm so wie es hier steht funktioniert ?

Probier es doch einfach mal aus, der µC geht schon nicht kaputt dabei.

von Christian K. (christiankarle)


Lesenswert?

Peter II schrieb:
> Die frage ist ob du die Richtigen Daten empfängst. Was ist wenn du den
> µC erst einschaltet wenn schon Daten übertragen wurden? du ließt ja
> immer 10 Zeichen ohne das du wirklich weißt wo Anfang und ende ist.
>
> Aber das kommt darauf an was du überhaupt machen willst.

Mein Tagesziel heute, war zu verstehen wie der Datenempfang mit dem 
USART funktioniert und wie man diese Speichern kann, mittels eines 
Interrupts.

Ich habe auch erst am Montag angefangen mit der Programmiersprache C.
Mein nächstes Ziel ist genau das von Ihnen angesprochene.

-> Werde dann die Hilfe des Forums sicher wieder in Anspruch nehmen 
müssen. Aber erst mal selber Kopfzerbrechen. :)

Vielen Dank für Eure Hilfe,

Christian


P.S: Bitte Kommentiert falls noch Fehler enthalten sein sollten:)

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
Noch kein Account? Hier anmelden.