Forum: Mikrocontroller und Digitale Elektronik Probleme mit fgets() und write() - RS232


von St M (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe folgendes Problem: Ich möchte einen String an meinen Seriellen 
Monitor(Arduino Uno R3, Arduino IDE 1.5.7) einen String senden. Das 
klappt soweit auch ganz gut, allerdings wird irgendwie zu dem 
eingegebenen String immer noch etwas dazugesendet. strlen() gibt mir 
aus, der string sei immer 1 Zeichen länger als eingegeben(\0 mit 
eingerechnet). Empfangen wird allerdings immer der String(bei längeren 
Strings aber um ein wenig gekürzt) mit irgendwelchen zusätzlichen 
Zeichen(immer andere). Wenn ich also beispielsweise "hallowelt" sende, 
kommt folgendes am seriellen Monitor an:
00010110h104
10000110a97
00110110l108
00110110l108
11110110o111
11101110w119
10100110e101
01101101�182
01011101�186
11000010C67
10000100!33
00000111�224
Und auf gesendet werden 11 Zeichen.
Ich kann auch kein \0 Zeichen finden. Wenn ich "asdf" sende, kommt er 
vollständig an(\0 abgesehen) und mit zwei zusätzlichen Zeichen("\r", 
"\n")
10000110a97
11001110s115
00100110d100
01100110f102
1011000013
01010000
10
00000001�128
Und ggesendet werden 6 Zeichen.
Ich wäre euch sehr dankbar wenn ihr mir irgendwie helfen könntet. Dei 
beiden Skripte findet ihr im Anhang.

PS: Schaltung ist folgende:
Arduino Pin D4----Inverter----RS232 Pin 3(TxD)
Arduino GND----RS232 Pin 5(GND)
PPS: Mein Computer(Sender) hat folgende Daten: IBM Think Pad T23, Intel 
Pentium 3, 512MB Arbeitsspeicher, Arch Linux mit Kernel 3.14.6

von Uwe (Gast)


Lesenswert?

Guten Tag St M,

Wie hoch ist die Baudrate und der Baudratenfehler ?

von St M (Gast)


Lesenswert?

Die BaudraTE SIND 75 Baud und den Baudratenfehler weiß ich nicht(stty 
gibt mir keine Auskunft?!)

von Uwe (Gast)


Lesenswert?

Hallo,

also machst Du Funkfernschreiben?

http://de.wikipedia.org/wiki/Funkfernschreiben

Sehr eigenartig !

Da solltest Du dir erst mal klar über die technischen Spezifikationen 
werden, ohne diese kann man doch logisch keine Fehlersuche betreiben.

Ok ?

von Dr. Sommer (Gast)


Lesenswert?

Bitte Compilerwarnungen lesen und beherzigen:
* Es fehlt #include <unistd.h>
* Es muss "int fd" und nicht "unsigned int fd" sein
* &*c ist sinnlos, einfach "c" tuts auch
* laenge sollte vom Typ size_t sein

Vermutlich ist dein Terminal nicht korrekt eingestellt. Bei 
Standardeinstellungen verarbeitet Linux (UNIX) die zu übertragenden 
Daten und ändert Zeichen, fügt welche hinzu etc. So öffnet man ein 
Terminal unter Linux und konfiguriert es so, dass es alles so belässt 
wie es ist:
1
int fd = open (filename.c_str (), O_RDWR | O_NOCTTY);
2
if (fd == -1) return;
3
4
termios t;
5
tcgetattr (m_fd, &t);
6
t.c_lflag = 0;
7
t.c_iflag = 0;
8
t.c_oflag = 0;
9
t.c_cflag = CS8 | CREAD | CLOCAL;
10
for (size_t i = 0; i < NCCS; ++i) {
11
  t.c_cc[i] = _POSIX_VDISABLE;
12
}
13
t.c_cc[VMIN] = 1; // Jedes Zeichen sofort senden
14
t.c_cc[VTIME] = 20;  // 20 Sek read-Timeout
15
cfsetospeed (&t, B115200); // Hier Baudrate angeben
16
cfsetispeed (&t, B115200);
17
if (tcsetattr (fd, TCSANOW, &t) != 0) {
18
  close (fd);
19
}

von St M (Gast)


Lesenswert?

Der Compiler hat mir keine Warnungen ausgegeben. Aber das ich fd 
unsigned gemacht habe verstehe ich auch nicht

von Dr. Sommer (Gast)


Lesenswert?

St M schrieb:
> Der Compiler hat mir keine Warnungen ausgegeben.
Dann machs dir zur Gewohnheit immer mit "-Wall -Wextra" zu kompilieren. 
Warnungen werden zwar oft als lästig empfunden, aber die bemängelten 
Probleme können durchaus real sein, und wenn es trotzdem funktioniert 
ist das oft bloßer Zufall.

von nicht-C-könner (Gast)


Lesenswert?

Man schaue sich einfach mal die ASCII werte aller Zeichen an und man 
wird feststellen, dass fgets anscheinend ein newline Zeichen (ASCII 10) 
vor das stringende schreibt: einfach das newline zeichen durch das 
stringende Zeichen ersetzen.

von nicht-C-könner (Gast)


Lesenswert?

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>

int main(void){
  int laenge;
  char c[100];
  const char *port = "/dev/ttyS0";
  unsigned int fd = open(port, O_RDWR | O_NOCTTY);
  if(fd == -1){
    printf("Falscher Port(name)\n");
    return 1;
  }
  printf("\e[1;31mBitte String eingeben: \n\e[0m");
  fgets(c, 99, stdin);
  laenge = strlen(c);
  c[laenge - 1] = c[laenge]; // \n durch \0 ersetzen
  printf("\e[1;34m%d\n%d\n\e[0m", laenge, c[laenge]);
  printf("Daten werden gesendet. Bitte warten...\n");
  write(fd, &*c, laenge);
  return 0;
}

von Dr. Sommer (Gast)


Lesenswert?

nicht-C-könner schrieb:
> einfach das newline zeichen durch das
> stringende Zeichen ersetzen.
Wie soll denn das Ersetzen des letzten newline-Zeichens die 
newline-Zeichen nach jedem einzelnen Zeichen des String loswerden?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

nicht-C-könner schrieb:
> write(fd, &*c, laenge);
------------^^^
Was soll das da?

von St M (Gast)


Lesenswert?

Ich hatte mir eingebildet der Compiler möchte da gerne eine Referenz 
haben und mit nur C würde er nur wi Zeichen lesen. Geht aber auch so. 
Danke.
Zum Teil lag es wirklich am newline Zeichen. Allerdings sendet er 
trotzdem immernoch zwei Zeichen zu falsch. Liegt das an einer 
Verschiebung im Arduino skech?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

St M schrieb:
> Ich hatte mir eingebildet der Compiler möchte da gerne eine Referenz
> haben

In C gibt es keine Referenzen.

von St M (Gast)


Lesenswert?

Habe wohl c und c++ vermischt...
Aber ich habe jetzt auch noch einmal den Tipp von Dr. Sommer getestet, 
mit der termios Struktur, hat aber Ich nichts gebracht. Ich habe jetzt 
die Werte noch einmal mir den ASCII werten verglichen und festgestellt, 
dass irgendwie ab 8 Zeichen um 1 nach links verschoben wird. Und dann 
bei der nächsten Binärstelle dann 1 weiter usw.

von St M (Gast)


Lesenswert?

Ich habe jetzt die Ursache gefunden:
Der Arduino skech dauert zu lange, sodass ich spätestens nach 11 zeichen 
in Zeitverzug komme.
Aber trotzdem danke an alle, die mit geholfen haben.

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.