Forum: PC-Programmierung Zuviele Enter


von Päät (Gast)


Lesenswert?

Moin an alle,

ich will eine UART Schnittstelle auf meinem PC auslesen und in einem 
File speichern
1
#include <stdio.h>
2
#include <fcntl.h>   /* File Control Definitions           */
3
#include <termios.h> /* POSIX Terminal Control Definitions */
4
#include <unistd.h>  /* UNIX Standard Definitions      */ 
5
#include <errno.h>   /* ERROR Number Definitions           */
6
7
void main(void) {
8
   ssize_t nrd;
9
   int fd;
10
   int fd1;
11
   char buffer[256];
12
13
   fd = open("/dev/ttyUSB1", O_RDONLY);
14
   fd1 = open("text.txt", O_CREAT | O_WRONLY); /*S_IRUSR | S_IWUSR*/
15
   while (nrd = read(fd,buffer,256)) {
16
      write(fd1,buffer,nrd);
17
   }
18
   
19
   close(fd);
20
   close(fd1);
21
}

Mein uC überträgt nach jeder Information ein "\n", soweit ist die 
Anzeige, wenn ich Minicom als Konsole benutze richtig. Mit meinem Code 
wird jetzt aber in der .txt-Datei zwei "\n" eingefügt. Nehm ich das "\n" 
aus dem Programmcode meines uC raus, habe ich keine Enter mehr drin.

Weiß jemand abhilfe?

Vielen Dank für alle konstruktiven und nicht konstruktiven Beiträge

Patrick

von wendelsberg (Gast)


Lesenswert?

Päät schrieb:
> Mit meinem Code
> wird jetzt aber in der .txt-Datei zwei "\n" eingefügt. Nehm ich das "\n"
> aus dem Programmcode meines uC raus, habe ich keine Enter mehr drin.
>
> Weiß jemand abhilfe?

Naheliegender Gedanke: Korrigiere das uC-Programm.

wendelsberg

von Päät (Gast)


Lesenswert?

wendelsberg schrieb:
> Naheliegender Gedanke: Korrigiere das uC-Programm.

Nunja, ich verwende in meinem uC-Programm ein \n.
-wenn ich das nun weglasse, habe ich in meinem txt-File kein \n mehr 
drin.
-die Konsole zeigt es richtig an, bedeutet, in dem Programmcode muss 
irgendwo (vermutlich bei der read Stelle) ein weiteres \n eingefügt 
werden.

Patrick

von Luther B. (luther-blissett)


Lesenswert?

/dev/ttyUSB0 ist ja nicht einfach die serielle Schnittstelle, sondern 
die serielle Schnittstelle als TTY - d.h. du hast möglicherweise 
Transformationen in input und output. Ich würde daher zuerst mal darauf 
tippen, daß daß der µC in Wirklichkeit '\r\n' am Zeilenende sendet und 
daß für /dev/ttyUSB das 'OCRNL' Flag aktiv ist (das übersetzt \r nach 
\n, was unter meiner Annahme zur Duplizierung führen würde). Du kannst 
ja mal nachgucken, was

$ stty -a -F /dev/ttyS0

ausgibt und ob da "ocrnl" steht (ohne Minus vorne dran).

In jedem Fall solltest du noch mal 
https://en.wikibooks.org/wiki/Serial_Programming/termios durchlesen, wie 
du diese Transformationen ein oder ausschalten kannst.

: Bearbeitet durch User
von wendelsberg (Gast)


Lesenswert?

Päät schrieb:
> bedeutet, in dem Programmcode muss
> irgendwo (vermutlich bei der read Stelle) ein weiteres \n eingefügt

Also schreibe Dir eine Dump-Ausgabe zwischen read und write.

wendelsberg

von Kopfschüttel (Gast)


Lesenswert?

Re: Zuviele Enter
Männliche Enten heissen Erpel, nicht Enter, auch im Plural.






zum tieferen Sinn dieses Postings:
Denkt doch einfach mal nach bevor ihr so unsinnige Betreffs schreibt. 
Siehe auch Netiquette und Forum-Fragenformulierung

von Dirk B. (dirkb2)


Lesenswert?

Sind es wirklich zwei \n oder ist es \r\n ?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Luther B. schrieb:
> würde daher zuerst mal darauf tippen, daß daß der µC in Wirklichkeit
> '\r\n' am Zeilenende sendet und daß für /dev/ttyUSB das 'OCRNL' Flag
> aktiv ist (das übersetzt \r nach \n, was unter meiner Annahme zur
> Duplizierung führen würde).

Du meinst ICRNL, nicht OCRNL, denn schließlich nimmt der PC die Zeichen 
als Eingabe entgegen. Ausgegeben wird ja offenbar auf /dev/ttyUSB 
nichts.

Erklärung: Wenn der µC ein \r\n schickt, wird wegen ICRNL das erste 
Carriage-Return in \n verwandelt. Der PC sieht dann: \n\n.

@TO: Ja, Du musst /dev/ttyUSB in den Raw-Mode versetzen, sonst werden 
diverse Zeichen vom TTY-Driver gemapped. Google mal nach "tty raw mode" 
bzw. nach "man termios".

Gib mal ein der Shell ein:
1
stty -a </dev/ttyUSB

und poste hier den Output.

Folgende Input flags sollten mindestens gelöscht werden:

c_lflag: ISIG, ICANON, ECHO
c_iflag: ICRNL

Desweiteren solltest Du noch VMIN auf einen vernüftigen Wert setzen, 
z.B. 1. VTIME sollte auf 0, damit der Input blockiert, wenn keine 
Zeichen empfangen werden.

Danach wirst Du \r\n als Zeilentrenner erhalten, also weiterhin 2 
Zeichen und nicht eines. Wenn Du damit leben kannst, ist das okay. 
Schließlich hast Du dann eine Datei, wie sie auch Windows oder DOS 
speichern würden, da sie immer \r\n als Zeilentrenner in einer 
Text-Datei verwenden. UNIX/Linux benutzt nur \n, kann aber mit 
Windows-kompatiblen Dateien durchaus umgehen.

Wenn Du nur \n empfangen willst, musst Du das auf dem µC anpassen, indem 
Du das Senden von \r unterbindest, also nur das '\n' sendest. Oder Du 
änderst Deine simple read-write-Schleife derart ab, dass Du das \r auf 
dem PC herausfilterst:
1
while (nrd = read(fd,buffer,1))
2
{
3
    if (nrd > 0 && buffer[0] != '\r')
4
    {
5
        write(fd1,buffer,nrd);
6
    }
7
}

Wenn Dich hier stört, dass die Zeichen zeichenweise einzeln auf die 
Datei geschrieben werden, hier der Tipp: Nutze für Datei-I/O möglichst 
die stdio-Lib, also fopen/fputc statt open/write. stdio ist im Zweifel 
immer effizienter, als Du es mit open/write sein kannst, da es an das 
System angepasste Buffer-Strategien nutzt. Du kannst mit stdio immer 
guten Gewissens die Zeichen einzeln auf die Datei schreiben. Die 
stdio-Lib mapped das automatisch in Block-IO (z.B. in 1K-Blöcke). Falls 
Dich die größeren Blöcke jedoch wieder stören: "man fflush"

Es gibt also jede Menge Möglichkeiten.

: Bearbeitet durch Moderator
von Luther B. (luther-blissett)


Lesenswert?

Frank M. schrieb:
> Du meinst ICRNL, nicht OCRNL, denn schließlich nimmt der PC die Zeichen
> als Eingabe entgegen. Ausgegeben wird ja offenbar auf /dev/ttyUSB
> nichts.

Ja, sorry, Richtungen verwechselt. ;)

von Rolf M. (rmagnus)


Lesenswert?

Päät schrieb:
> #include <termios.h> /* POSIX Terminal Control Definitions */

Du bindest den termios-Header ein, benutzt aber nicht die Funktionen 
daraus. Siehe z.B:

https://en.wikibooks.org/wiki/Serial_Programming/termios

Päät schrieb:
> while (nrd = read(fd,buffer,256)) {
>       write(fd1,buffer,nrd);
>    }

Das führt bei einem Fehler zu einer Endlosschleife.

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.