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 :)
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
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
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
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:)
Tut mir leid, habe sie vergessen anzuhängen :D Hier ist sie :)
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 !
> 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
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.
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.
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.
Das hier kann man kürzer schreiben: uart_string[String_Counter]=Temp; String_Counter++; so: uart_string[String_Counter++]=Temp;
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!
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?
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
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?
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.
Bedeutet dass, das mein Programm so wie es hier steht funktioniert ?
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.