Hallo,
ich versuche mit Interrupt über serielle Schnittstelle mehrere String zu
empfangen. Das Programm läuft nicht gut.Ich kann das erte String ohne
Problem empfangen aber mit dem zweiten String empfange ich nur die 2
erste Buchstaben.
Sieht jemanden wo das Problem liegt?
Anbei meine Code für das Senden und Empfangen
Ich danke euch für alle Hilfe.
Katia
Na, das ist ja reichlich Kuddelmuddel.
> #include <avr/iocan128.h>> #include <avr/iocanxx.h>> #include <avr/io.h>
Wenn mcu richtig gesetzt ist, reicht das Includen von io.h.
Das Obige compiliert gar nicht.
> #include "receive.h"
Wo ist die?
> main.c:
1
chartempstr[200];
2
unsignedcharnextCharPos;
3
volatileunsignedcharstringReady;
4
//volatile unsigned char dekryptString[100];
5
charstring[200];
6
intlendekryptString;
7
charreceivedString[200];
8
//const char dekryptString[14][100];
9
inti=0;
10
constchardekryptString[200];
> receive.c:
1
chartempstr[200];
2
charstring[200];
3
charbuffer[200];
4
unsignedcharnextCharPos;
5
intlendekryptString;
6
constchardekryptString[200];
7
volatileunsignedcharstringReady;
Du definierst diverse Variablen mehrfach. Du kannst sie zwar beliebig
oft deklarieren, aber nur einmal definieren. Nimm dein C-Buch zur Hand
und schlag "extern" nach.
Hallo,
ich habe gelesen und auch korrigiert. Extern ist für "One definition
rule" d.h jedes Teil, egal ob Variable oder Funktion nur ein einziges
mal definiert werden darf.
Mit den Veänderungen bekomme ich immer das selbe Problem.
Ach jetzt raffe ich das erst.
Thomas = Katia.
Und ich dachte deine vorletzte Nachricht wäre ein hämischer Kommentar zu
den intellektuellen Fähigkeiten der Katia.
Nee, bin ich blöd.
Hallo Stefan,
es ist nicht was du denkst mein Freund heisst Thomas und manchmal achte
ich nicht darauf, welche Name steht, wenn ich einen neuen Beitrag
schreiben will.
Wir benutzen den selben Rechner.
1/ Kannst du ein Beispiel angeben, was das Programm machen soll und was
es im Moment leider macht? Was geht ins Programm rein und was kommt
raus?
2/ Hast du die Änderungen mit extern bereits eingebaut und getestet?
Diese Änderungen sind essentiell, um doppelte Variablen zu vermeiden.
Ich verstehe nicht, dass du mit deinem Code überhaupt vom Kompiler ein
lauffähiges Programm bekommst. Meine Kompiler würden sinngemäß mit
"Fehler doppelte Symbole" kotzen und abbrechen.
3/ Du kannst in der Empfangsroutine eine Stelle verbessern:
1
ISR(SIG_UART0_RECV)
2
{
3
unsignedcharc=UDR0;
4
5
if(c=='\r')
6
{// ist der String vollständig?
7
string[nextCharPos]='\0';
8
stringReady=1;
9
nextCharPos=0;
10
}
11
else
12
{
13
string[nextCharPos]=c;
14
nextCharPos++;
15
16
//
17
// Den string IMMER mit einem Nullbyte abschliessen!
18
//
19
string[nextCharPos]='\0';
20
}
21
}
Das ist aber mehr fürS gute Gefühl.
4/ In deinem Programm ist keinerlei Kotrolle, ob Puffergrössen
überschritten werden.
Damit ist das Laufzeitverhalten extrem von den empfangenen Daten
abhängig! Manche Daten können dem Programm den Todesstoss versetzen.
Beispiel
1
#define Ns 5
2
#define Nz 8
3
4
charFrameFormat[Nz][Ns];
5
char**test[50];
6
char*result=NULL;// initialisieren des Pointers
7
constchar*delims=" ";
8
9
result=strtok_r(dekryptString,delims,test);
10
while(result!=NULL)
11
{
12
strcpy(FrameFormat[sPtr],result);
13
result=strtok_r(NULL,delims,test);
14
...
Eine Eingabe "eine beliebige Eingabe" wird an den Leerzeichen in Würter
aufgetrennt. Die Rückgabewerte im Beispiel sind Zeiger auf
"Eingabe"
"beliebige"
"eine"
NULL
Bereits der zweite Rückgabewert würde über die Grenzen von
FrameFormat[1] hinausschreiben und was zerstören oder verstümmeln. Die
Dimension Ns wird gesprengt.
Die Eingabe "eingabe mit mehr worten als in FrameFormat Platz ist" wird
die Dimension Nz sprengen.
5/ Du musst aufpassen mit den Typen für die Variablen.
Das war, so wie die KOmmentare im Programm aussehen, anscheinend mal
richtig und wurde dann geändert.
1
constchardekryptString[200];
2
...
3
strcpy(dekryptString,receivedString);
Passt nicht. const bedeutet fix, nicht veränderbar. Da darf man nichts
reinkopieren (strcpy) und man darf darin nichts zerstückeln (strtok_r)!
Der Compiler sollte da eigentlich mosern. Überhaupt sollte der Compiler
sejr oft mosern, weil das mit dem extern fehlt.
Stefan "stefb" B. wrote:
> Überhaupt sollte der Compiler> sejr oft mosern, weil das mit dem extern fehlt.
Naja, der Compiler bemerkt die redefinierten Symbole ja gar nicht,
schließlich werden die C-Dateien unabhängig voneinander übersetzt. Und
der gcc-Linker legt sie kommentarlos auf identische Adressen, so dass
ihr Code diesbezüglich sogar funktionieren sollte. Trotzdem sollte das
natürlich geändert werden.
Ich meine mich zu erinnern, die Fehlermeldung (oder Warnung?) mit
doppelten Symbolen gesehen zu haben. Ich kann aber nicht 100% sicher
sagen, ob es bei der GCC AVR Toolchain war.
Compiler hatte ich im Sinn Gesamtpacket/Toolchain geschrieben. Klar ist
es so wie du schreibst, dass der Linker hier das Problem entdecken kann.
Der GCC hat die Eigenart, daß man auf extern verzichten kann (ohne
Warnung).
Alle anderen C-Compiler meckern aber darüber.
Um also portablen Code zu schreibe, sollte man es trotzdem verwenden.
Peter
Hallo,
im Moment versuche ich mehrere String an meinen Mikrocontroller über die
serielle Schnittstelle zu senden.
ZB: string1:"SEND AA BB CC "
string2:"RECV AA BB CC "
1)Ich kann der erste String sehr gut empfangen und in der Funktion
Derypt_Data_Cpu bearbeiten.
2)Für der zweite String bekomme ich nur die erste Buchstaben.
Im for schleife von Derypt_Data_Cpu habe ich nur FrameFormat[0]=RE\n und
dann gehe ich züruck im Main Funktion
3)Ich habe die Änderungen mit extern gemacht. Mit dem Aktuelzustand
bekomme ich keinen Fehler Meldung und Warnung
4)Ich benutze const damit die Variable im Programm nicht veändern wird.
Ich vermute:Falls der zweite String angekommen ist, wird es im
dekryptString gespeichert und weiter bearbeitet.
5)Im Sting gibt habe ich kein Wort länger als 5 Zeichen.
1/ Oben hatte ich Quatsch zur Reihenfolge der Auswertung beim strtok_r
geschrieben. Das fängt nicht "hinten" an, sondern "vorne".
2/ In dieser Zeile hast du ein Argument zuwenig, um das %d auszuwerten!
sprintf(tempstr," frame: %s\n, %d",FrameFormat[i]);
Das kann dir seltsame Laufzeitfehler bringen! Die tauchen dann auch nach
dem ersten String auf... Wenn 3/ und 4 unten nicht zutreffen ist sprintf
je der einzige Übeltäter, der ein \n in die Daten reinfutscheln kann.
3/ Du testest das Zeilenende des empfangenen Strings mit \r. Kann es
sein, dass dir von der Gegenseite auch ein \n geschickt wird und dass
das unglücklich im Empfangspuffer landet? Schon probiert in der
Interruptroutine nix zu machen, wenn das c == '\n' ist?
4/ Du sperrst die Interrupts IMHO zu lange. Es kann sein, dass noch die
ersten zwei Zeichen der zweiten Zeile im UART stehen, wenn der
Interrupts gesperrt wird. Dann gehen etliche Zeichen verloren, weil du
lange auswertest. Dann ist der Interrupt frei, die Zeichen RE aus der
UART werden herausgeholt aber inzwischen ist nur noch \n auf der Leitung
(wenn ein \n geschickt wird). Was steht in dekryptString direkt wenn du
in Dekrypt_Data_Cpu() ankommst und noch keine Auswertung gemacht hast?
5/ const ist an der Stelle falsch. Glaube es mir.