C-Code für Datenempfang mit USART

OP #3520796
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 :)
Angehängte Dateien:
#3520804
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
Gast #3520806
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
Gast #3520814
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
Gast #3520844
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 !
#3520855
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.
Gast #3520864
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.
#3520868
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.
#3520869
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.
#3520875
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!
OP #3520890
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?
Angehängte Dateien:
#3520894
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.
OP #3520907
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?
Angehängte Dateien:
Gast #3520916
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.
OP #3520929
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:)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren