Forum: Compiler & IDEs Empfangen mit Interrupt


von Katia (Gast)


Angehängte Dateien:

Lesenswert?

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

von Stefan E. (sternst)


Lesenswert?

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
char tempstr[200];
2
unsigned char nextCharPos;
3
volatile unsigned char stringReady;
4
//volatile unsigned char dekryptString[100];
5
char string[200];
6
int lendekryptString;
7
char receivedString[200];
8
//const char dekryptString[14][100];
9
int i=0;
10
const char dekryptString[200];
> receive.c:
1
char tempstr[200];
2
char string[200];
3
char buffer[200];
4
unsigned char nextCharPos;
5
int lendekryptString;
6
const char dekryptString[200];
7
volatile unsigned char stringReady;

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.

von Katia (Gast)


Lesenswert?

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.

von Stefan E. (sternst)


Lesenswert?

Dann poste bitte mal den korrigierten Code (bitte inklusive der 
receive.h).

von Katia (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
Anbei die Code

von Stefan E. (sternst)


Lesenswert?

Ich sehe nicht, dass du bei den Variablen-Definitionen irgendetwas 
verändert hättest.

von Katia (Gast)


Lesenswert?

hallo,
wie soll ich es dann machen?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Beispielsweise so, wenn du die angegeben Variaben als globale Variablen 
haben willst und wenn sie alle in main.v definiert werden sollen:
1
// > main.c:
2
char tempstr[200];
3
unsigned char nextCharPos;
4
volatile unsigned char stringReady;
5
//volatile unsigned char dekryptString[100];
6
char string[200];
7
int lendekryptString;
8
char receivedString[200];
9
//const char dekryptString[14][100];
10
int i=0;
11
const char dekryptString[200];
1
// > receive.c:
2
extern char tempstr[];
3
extern char string[];
4
extern char buffer[];
5
extern unsigned char nextCharPos;
6
extern int lendekryptString;
7
extern const char dekryptString[];
8
extern volatile unsigned char stringReady;

von Thomas (Gast)


Lesenswert?

Hallo,
ich glaube, dass Problem liegt anders.

von Thomas (Gast)


Lesenswert?

Hallo,
kann niemanden mir wirklich helfen?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von Johannes M. (johnny-m)


Lesenswert?

Stefan "stefb" B. wrote:
> Ach jetzt raffe ich das erst.
>
> Thomas = Katia.
Ah, ein Zwitter... Welch seltene Ehre!

von Katia (Gast)


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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
  unsigned char c = 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
  char FrameFormat[Nz][Ns];
5
  char **test[50];
6
  char *result=NULL; // initialisieren des Pointers
7
  const char *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
const char dekryptString[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.

von Stefan E. (sternst)


Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Katia (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von Katia (Gast)


Lesenswert?

Hallo Leute,
immer ohne Erfolg hat jemanden zuverlässig ein anderer Vorshlag.

Katia

von Stefan B. (stefan) Benutzerseite


Lesenswert?

plonk

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.