Forum: Mikrocontroller und Digitale Elektronik Empfange merkwuerdige Signale(Ausserirdische???)


von Paule (Gast)


Lesenswert?

Hei Leute,

Ich will 2 uC mit der seriellen Schnittstelle verbinden. Zum Test habe
ich den einen uC eine Endlos-Folge von A's senden lassen. Das klappt
auch ganz gut(danke Stefan und Karl-Heinz :-)).
Ich will nun 6 aufeinanderfolgende Zeichen(in diesem fall A's)
empfangen.
Wenn ich aber nun versuche dieses Signal mit nachfolgendem Code zu
empfangen, passiert etwas merkwuerdiges: Zuerst empfange ich immer 6
P's und zwar immer P's. Dann unterbreche ich das Signal kurz und nun
empfange ich immer A's egal wie oft ich das Signal noch wieder
unterbreche. Kann sich das einer erklaeren?????????
Ausserdem ist hinter den 6A's ein riesen langer Rattenschwanz an
Zeichen(ca.16 Stueck) was ich ebenfalls nicht evrstehe. Vielleicht hat
jemand von euch eine Ahnung. Falls es euch hilft der uP ist ein Rabbit
3000.
VG Paule

#define EINBUFSIZE 127        //Ein-/Ausgangsbuffer
#define EOUTBUFSIZE 127
#class static

//************************************************
void SerEReceive(char *s) {

      auto int i;
      serEopen(9600);        //serieller Port Initialisierung
      serErdFree;
      serErdFlush;
      serEflowcontrolOff();
      serEdatabits(PARAM_8BIT);

      while(1) { i=serEread(s,6,20);  //i gibt an wieviele Bytes
                 printf("%s*%d*",s,i);//erfolgreich empfangen wurden
                    }       //hier geschieht das Unfassbare!!!!
      serEclose();
                        }
//************************************************

main () {

          const char s1[]="B";

          SerEReceive(s1);
      }

von Neo81 (Gast)


Lesenswert?

Hmmmmm, bist du auch ganz sicher, das dein Eingangssignal korrekt ist?

von Paule (Gast)


Lesenswert?

100%, habe mit Oszi gemessen.

von bedenkenträger (Gast)


Lesenswert?

Start - Stopbits usw stimmen auf Sender und Enpfängerseite?

von Paule (Gast)


Lesenswert?

Ich habe auf beiden uC nichts besonderes eingestellt. Beide 8 Datenbit
und Standart ist beim Rabbit 1 Stoppbit, also muessten Start und
Stoppbit passen oder?.

von Stefan (Gast)


Lesenswert?

Überdenke deine Programmlogik! Was gibst du im Moment aus, wenn kein
Zeichen empfangen wurde? Ist das richtig? Wie könnte man erkennen, dass
kein Zeichen empfangen wurde?

von Sonic (Gast)


Lesenswert?

Sind evtl. die Signalpegel invertiert?

von Paule (Gast)


Lesenswert?

In dem Moment geb ich das aus, was im Speicher steht, also die letze
erfolgreich empfangene Char-Kette.

von Paule (Gast)


Lesenswert?

Nein, nicht invertiert, hab ich schon gecheckt.

von Thomas (Gast)


Lesenswert?

Könntest du bitte diese Betreffsverstümmelungen unterlassen?

von Paule (Gast)


Lesenswert?

Koenntest du bitte den Stock aus deinem Arsch nehmen Thomas?

von Thomas (Gast)


Lesenswert?

Ich guck grad mal nach. Hmmm, nein, ist grad nichts zu machen.

von yalu (Gast)


Lesenswert?

Ein A wird (incl. der Start-/Stopbits, bei 8 Datenbits, 1 Stopbit und
keiner Parität) als

    0100000101

übertragen, viele As entsprechend als

    0100000101010000010101000001010100000101...
      ^         ^         ^         ^

Startest du erst den Sender und dann erst den Empfänger, wird der
Sender irgendein 0-Bit, das auf ein 1-Bit folgt, als Startbit
interpretieren, bspw. auf eines der mit ^ markierten.

Der Empfänger liest also

    00000101010000010101000001010100000101...

Das erste Byte (incl. Start-/Stopbit) ist

    0000010101

Dies entspricht einem P, die folgenden Bytes natürlich entsprechend.

Unterbrichst du den Sender für eine Weile sendet er ständig 1-Bits
(das ist der Ruhezustand). Danach synchronisiert sich der Empfänger
auf das richtige Startbit. Dann klappt's auch mit den As.

von Paule (Gast)


Lesenswert?

Hei Thomas, du verstehst also doch Spass, Respekt(ernst gemeint).

von Paule (Gast)


Lesenswert?

Das klingt gut, danke. 1. Frage beantwortet. Danke Yalu. BIst wohl kein
son Stuemper wie ich ;-).
Aber weisst du auch warum 16 Zeichen Muell hinter jeden empfangenen
A's stehen???

von yalu (Gast)


Lesenswert?

Ich kenne weder den Rabbit noch die Funktion ser Eread, aber
vermutlich liegt es an Folgendem:

serEread liest 6 Bytes von der Schnittstelle und schreibt diese in s.
Wenn s mit dem format "%s" (also als String) ausgegeben wird, muss s
nullterminiert sein, sonst findet printf das Stringende nicht und
zeigt solange Zeichen an, bis es zufälligerweise eine Null findet.
Füge mal die Zeile

  s[i] = '\0';

vor dem printf ein.

Des Weiteren ist

  const char s1[] = "B";

nicht richtig. Damit wird s1 mit der Göße 2 angelegt ('B' und das
Nullzeichen), was zu klein ist, um 6 + 1 Zeichen zu speichern. Das
kann seltsame Folgen haben.

Außerdem ist das const nicht richtig, denn du willst die Variable ja
ändern (normalerweise sollte der Compiler mindestens eine Warnung
ausgeben). Also besser durch

  char s1[7];

ersetzen.

von Paule (Gast)


Lesenswert?

Es funktioniert. hattest recht mit dem, dass printf einen
nullterminierten String sucht. Yalu ich liebe dich ;-).
Gruss Paule

von yalu (Gast)


Lesenswert?

> Yalu ich liebe dich

Aua ;-)

Trotzdem gern geschehen

von Paule (Gast)


Lesenswert?

Hei Leute, nochmal ne Frage:
Das Programm laeuft jez einwandfrei, wenn ich es in den SRAM-speicher
compiliere, sobald ich es aber in den EEPROM-Speicher compiliere(was
ich natuerlich irgendwann muss) wird auf dem Bildschirm
BBBBBBBBBBBBBBBBB ausgegeben statt AAAAAA. Wenn ich nach SRAM
compiliere bringt der Compiler die Warnung:

line 1014 : WARNING IDBLOCK.LIB   : Cannot access user block while
running in RAM.

Wenn ich nach EEPROM compiliere kommt keine Fehlermeldung, aber wie
gesagt, dann funktionierts au net.
Vielleicht kann einer von euch Geniusen mir weiterhelfen.
Nochmals VG Paule.
Unten habe ich den aktuellen Code gepostet.

#define EINBUFSIZE 127        //Ein-/Ausgangsbuffer
#define EOUTBUFSIZE 127
#define DINBUFSIZE 127        //Ein-/Ausgangsbuffer
#define DOUTBUFSIZE 127

#class static

//************************************************
void SerEReceive(char *s) {

      auto int i;
      serEopen(9600);        //serieller Port Initialisierung
      serErdFree;
      serErdFlush;
      serEflowcontrolOff();
      serEdatabits(PARAM_8BIT);

do {
          i=serEread(s,6,20);
         } while(i<6);

      s[i] = '\0';
      printf("%s",s);
      for(i=0; i<29999; i++) {i++; i--;} ;
      serEclose();
                        }
//************************************************

main () { const char s1[]="BBBBBBBBBBBBBBBBBBBBBBBBBBBBB";

    brdInit(); //Prototypboard initialisieren

Start:    SerEReceive(s1);
          SerDwrite(s1);   //nicht wichtig fuer Problem
          goto Start;

      }

von yalu (Gast)


Lesenswert?

Lass doch endlich mal das const in der Definition von s1 weg!

Wie schon oben gesagt: Du willst die Variable ja ändern. Das const
bewirkt vermutlich, dass der Compiler s1 ins ROM legt, weswegen die Bs
nicht durch die As überschrieben werden können.

von Paule (Gast)


Lesenswert?

Ich muss aber die Variable als const deklarieren, sonst nimmt sie der
Compiler nicht an. Oder wie genau soll ich sie deklarieren, damit s1
ins Ram gelegt wird?

von Paule (Gast)


Lesenswert?

OK, hattest Recht Yalu, der Compiler spuckt zwar dann ne Warnung aus,
aber es funktioniert!

von yalu (Gast)


Lesenswert?

Was meckert der Compiler, wenn du das const weg lässt?

Geht auch

  char s1[7];

(ohne Initialisierung) nicht?

Evtl. hilft es, wenn du das const durch static ersetzst (vielleicht
kann der Compiler keine Array auf den Stack legen, wie gesagt, ich
kenne weder die Rabbit-Architektur, noch den Compiler), also so:

  static char s1[] = "BBBBBBBBBBBBBBBBB";

oder so:

  static char s1[7];

von Karl heinz B. (kbucheg)


Lesenswert?

const ist englisch und bedeutet 'konstant'.
Wenn etwas konstant ist, dann geht der Compiler davon
aus, dass es sich nie aendern wird. Was sich aber niemals
aendert kann auch in einem Eprom abgelegt werden.

Du willst aber, dass sich die Variable ändern kann. Du willst
ja, dass die Zeichen von der Seriellen dort abgespeichert werden.
Also kann diese Variable nicht const sein!
Verstehst du das nicht?

> const char s1[]="BBBBBBBBBBBBBBBBBBBBBBBBBBBBB";

Wozu schreibst du da überhaupt was hinein? Es wird ja
sowieso von der Empfangsroutine überschrieben. Lass das
halt einfach weg.
Abgesehen davon, ist

  char s1[] = "BBBBBBBBBBBBBBBBBBBBBBBBBBBB";

100% legaler, richtiger C Code. Wenn dein Compiler das nicht
annimmt, dann hat er einen Fehler. Aber wie gesagt, du brauchst
da nichts vorgeben, da die Empfangsroutine ja sowieso
was reinschreibt:


  char s1[20];    /* Platz für 20 Zeichen */

> Ich muss aber die Variable als const deklarieren, sonst nimmt sie
> der Compiler nicht an

Das ist der blödeste Grund überhaupt. Solange du so programmierst
kann man dir nur einen Rat geben: Kauf dir ein Buch über
C Grundlagen.

von Paule (Gast)


Lesenswert?

Ihr habt ja so recht. Ich habe gedacht, const bedeutet, dass der String
an einer festen Stelle gespeichert wird, aber dazu benutzt man ja
static(tragische Verwechslung). Jetzt wird mir so einiges klar.... Der
Compiler spuckt jetzt auch keine Warnung mehr aus. Danke und sorry
wegen meiner Unfaehigkeit.

von Paule (Gast)


Lesenswert?

Hello again,
wieder Probleme....

Der uC sendet mit untem geposteten Programm nix, nur wenn ich eine
Endlosschleife mit serDwrite mache, dann klappts einwandfrei. Das
versteh ich ueberhaupt nicht, ist doch sehr komisch oder, dass er nur
bei einer Endlosschleife sendet. Er gibt auch immer an, dass er 6
Zeichen erfolgreich gesendet hat.
kann vielleicht jemand den Code checken oder weiss jemand was???
VG Paule



#define DINBUFSIZE 127
#define DOUTBUFSIZE 127
#class static

//************************************************
void SerDwrite(char *s) {

      int i,j;
      j=0;
      serDopen(9600);
      serDwrFree;
      serDwrFlush;
      serDflowcontrolOff();
      serDdatabits(PARAM_8BIT);

      while(j<6) { j=serDwrite(s,6); } //return-Wert von j ist
                                       //erfolgreich
                                       //gesendete Bytes
      serDclose();
                   }
//************************************************

main () {

          char s1[50];
          gets(s1);

          SerDwrite(s1);  //Habe unten die Fkt-Def. von SerDwrite
                          //angehaengt, falls es was hilft
         }

/* START FUNCTION DESCRIPTION
********************************************
serDwrite                   <RS232.LIB>

SYNTAX:       int serDwrite(void *data, int length);

DESCRIPTION:   Transmits length bytes to serial port D.
               This function is non-reentrant.

PARAMETER1:    data  : data structure to write to serial port D
               length: number of bytes to write

RETURN VALUE:  The number of bytes successfully written to serial port
D.

END DESCRIPTION
**********************************************************/

nodebug int serDwrite(void *data, int length)
{
   static int bytesleft;
   static char *p;

   p = (char *)data;
   bytesleft = length;
   if (cbuf_wrlock(spd_ocbuf))
   {
      while (bytesleft)
      {
         bytesleft -= cbuf_put(spd_ocbuf, p+(length-bytesleft),
bytesleft);
         spd_starttx();
      }
      cbuf_wrunlock(spd_ocbuf);
   }
   return length - bytesleft;
}

von Paule (Gast)


Lesenswert?

Hi.
Habe es nun auch mit andern Sendefunktionen(serDputs) ausprobiert und
es ist immer das gleiche, nur wenn ich eine Endlosschleife dranhaenge,
funktioniert es. Ist das vielleicht generell so, das ich eine Schleife
o.ae. programmieren muss, um seriell Daten zu versenden??? Komme nicht
weiter an der Stelle, habe alles ausprobiert, waer cool wenn mir jemand
helfen koennte.
Gruss Paule

von Stefan (Gast)


Lesenswert?

Möglicherweise ist die Schnittstelle noch nicht bereit, wenn du bereits
versuchst Zeichen zu senden.

Die while() Schleife probiert es halt solange, bis tatsächlich mal 6
Bytes rausgegangen sind. Das übertüncht die Probleme.

Um diese These zu prüfen, schau dir den Rückgabewert von serDwrite()
an, wenn du kein while() verwendest.

Ich vermute die Probleme in einer nicht handbuchgemäßen Initialisierung
der seriellen Schnittstelle in Verbindung mit der Funktion
cbuf_wrlock().

Steht im Datenblatt vom µC und dessen UART was von einzuhaltenden
Delays und was macht die Funktion cbuf_wrlock() in deinem Spezial-C?

von Paule (Gast)


Lesenswert?

du hattest Recht Stefan,

das Problem war, dass ich die serielle Schnittstelle schon geschlossen
hab, obwohl noch nicht alle Daten aus dem Buffer gelesen wurden. Ich
hab das Problem dann geloest, indem ich das dazugehoerige
Statusregister abgefragt hab und erst bei erfolgter Sendung die
Schnittstelle geschlossen habe.

Danke fuer den Tipp!!!!!

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.