Moin,
ich habe ein Gerät das 30Sec lang ASCII Zeichen sendet und diese will
ich empfangen und bearbeiten.
Als System ist ein Debian vorhanden mit gcc.
Ich habe schon versucht so was zu lesen:
res = read(fd,(char *)buf,sizeof(buf));
aber irgendwie kommen da nur ca.9 Zeilen an....Ist das die große des
Hardware Buffers? Wie zeichnet mann denn alles auf in C?
Ich wäre für einen Tip dankbar
Lars
> Ich habe schon versucht so was zu lesen:>> res = read(fd,(char *)buf,sizeof(buf));
Na nur damit wirst Du nicht weit kommen :-) Zeig mal den ganzen
Quellcode. Falls Du das nicht möchtest lies wenigstens die Manpage.
Lars schrieb:> Ich habe schon versucht so was zu lesen:>> res = read(fd,(char *)buf,sizeof(buf));>> aber irgendwie kommen da nur ca.9 Zeilen an....Ist das die große des> Hardware Buffers?
Wie groß ist denn dein Buffer?
> Wie zeichnet mann denn alles auf in C?
read() in einer Schleife aufrufen.
Moin,
ich habe den Buffer schon auf > 10000 gestellt aber es kommen immer
gleich wenig Zeichen.
Ich habe noch nicht viel Code...ich geben den Buffer danch einfach per
Prinf aus.
Wenn ich eine while Schleife wie bekomme ich denn alle Daten in eine
Variable?
Ich will ja alle gesammelten Daten zusammen auswerten.
Lars
Lars schrieb:> aber irgendwie kommen da nur ca.9 Zeilen an....Ist das die große des> Hardware Buffers? Wie zeichnet mann denn alles auf in C?
Wenn Du folgendes durchliest, sollten alle deine Fragen vorerst gelöst
sein (geht ab "Programmierung mit C" los):
http://www.netzmafia.de/skripten/hardware/Seriell/index.html
Lars schrieb:> ich habe den Buffer schon auf > 10000 gestellt aber es kommen immer> gleich wenig Zeichen.
Dann ist wohl der interne Puffer voll.
> Wenn ich eine while Schleife wie bekomme ich denn alle Daten in eine> Variable?
Du merkst dir einfach, wieviele Zeichen schon gelesen wurden und
übergibst read() halt als Startposition die entsprechende Stelle in
deinem Puffer statt dessen Anfang.
Du mußt auch noch definieren, was "alle Daten" sind. Mit anderen Worten:
Du brauchst eine Möglichkeit, das Ende zu erkennen. Hast du dir dazu
schon Gedanken gemacht?
> ich habe den Buffer schon auf > 10000 gestellt aber es kommen immer> gleich wenig Zeichen.
Sachichdoch - Manpage lesen wäre zweckmäßig.
> Wenn ich eine while Schleife wie bekomme ich denn alle Daten in eine> Variable?
Mitzählen. Das war jetzt einfach :-)
Lars schrieb:> Warum kann ich den dem While kein Strcopy machen? Da hängt das Programm
Ja, hast du denn überhaupt Strings?
Ich seh schon.
WIr sind wieder mal an dem Punkt an dem man sagen muss: Es hilft alles
nichts. Wer Programm in der realen Welt schreiben will muss erst mal die
Grundlagen lernen! Das geht nun mal nicht so, wie sich manche das
vorstellen: vormittags den Entschluss gefasst Programmierer zu werden,
und nachmittags die Killerapplikation geschrieben, die einen reich
macht.
Karl Heinz Buchegger schrieb:> Lars schrieb:>>> Warum kann ich den dem While kein Strcopy machen? Da hängt das Programm>> Ja, hast du denn überhaupt Strings?
Und ehe du dich in einen Wirbel reinredest.
Nein, du hast erst mal keine Strings.
read befüllt dir den buffer mit den Zeichen die gerade da sind bzw. in
den buffer passen. Nicht mehr und nicht weniger. Von Strings kann zu
diesem Zeitpunkt noch überhaupt keine Rede sein.
Lars schrieb:> Ist nicht ein Char ein String?
Nein das ist ein Array of Bytes, In C sind Strins mit \0 terminert. Dann
sind es Strings und können mit den Funktionen aus der string.h behandelt
werden. Sonst ist das nur irgendwelcher Datenkram...
Gegenvorschlag:
char *spei; // Wir machen einen Pointer daraus
spei = (char)malloc(10000) // Speicher reservieren;
char *mark;
mark = spei; // alten Pointer merken
do{
res = read(fd,(char *)buf,sizeof(buf));
if (spei < mark + 10000) { // Sicher stellen, dass nocht über den
allocierten Speicher geschrieben wird
memcpy(spei, buf, res); // anzahl der gelesenen Zeichen umschaufeln
spei += rc // pointer hochzählen
}
}while( res > 0);
// hoffen, dass es sich um strings handelt, sonst als letztes Zeichen \0
anfügen
printf("read:%s\n",mark); // nicht wundern, wir nehmen hier den Anfang
des spei Pointers, da wir den ja oben laufend verschoben haben
// Speicher wieder frei geben
free(spei);
free(mark);
So, das ist nicht getestet, sollte aber gehen..
Grpßle aus dem Ländle von Jörg
Jörg Bernau schrieb:> So, das ist nicht getestet, sollte aber gehen..
Wenn die kleinen Elflein kommen und die Speicherlecks entfernen. Ja dann
funzt es xD
-->siehe malloc
->res = read(fd,(char *)buf,sizeof(buf)); ^^
wohle eher res = read(fd, buf, sizeof(buf) / sizeof(buf[0]);
-->memcpy(spei, buf, res); // anzahl der gelesenen Zeichen umschaufeln
spei += rc // pointer hochzählen
SoSo ^^
--> Speicher wieder frei geben
char *spei; // Wir machen einen Pointer daraus
spei = (char)malloc(10000) // Speicher reservieren ^^ Witzig
char *mark;
...
mark = spei; // alten Pointer merken
free(spei);
free(mark);
:) jaja speicher von einem nicht reservierten Speicherbereich freigeben
xD
Sry, musste sein.
:)
Jörg Bernau schrieb:> spei = (char)malloc(10000) // Speicher reservieren;
Wozu denn malloc, wenn die Größe eh als Konstante vorgegeben ist? Mal
abgesehen von dem überflüssigen und hier auch noch falchen Cast.
Ok danke für die Tips.
Aber ein Problem habe ich immer noch.....
Wenn ich z.b das hier:
1
charstring[]="Die schoenen Dinge im Leben sind umsonst.";
2
intlaenge=strlen(string);
3
printf("Laenge: %d Zeichen\n",laenge);
In meinen Code einfüge bleibt da das Programm stehn :-(
Ich habe auch das diese Includes drin:
/* lesen.c */
#include <termios.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
(Zwar nicht die Antwort auf Deine Frage)
Dem Compiler ist die Laenge des Strings bereits bekannt, weshalb ich
anstelle von strlen() sizeof() benutzen würde.
In dem Codeschnipsel ist kein Fehler, also muß er irgendwo anders
liegen. Sinnvoll ist es deshalb, ein minimales, aber vollständiges
Programm zu posten, das den Fehler noch enthält.
Folgendes Programm funktioniert bei mir jedenfalls einwandfrei:
1
/* lesen.c */
2
#include<termios.h>
3
#include<fcntl.h>
4
#include<sys/ioctl.h>
5
#include<stdio.h>
6
#include<sys/types.h>
7
#include<sys/stat.h>
8
#include<string.h>
9
#include<stdlib.h>
10
11
intmain(void)
12
{
13
charstring[]="Die schoenen Dinge im Leben sind umsonst.";
14
intlaenge=strlen(string);
15
printf("Laenge: %d Zeichen\n",laenge);
16
return0;
17
}
Es gibt aus:
1
Laenge: 41 Zeichen
Mehmet Kendi schrieb:> Dem Compiler ist die Laenge des Strings bereits bekannt, weshalb ich> anstelle von strlen() sizeof() benutzen würde.
Der Compiler (zumindest gcc) ist so intelligent, in so einem Fall auch
bei strlen() die Länge schon zur Compilezeit zu ermitteln.
Lass es Lars, hier wirst Du nicht wirklich eine "vernünftige" Antwort
erhalten.
BTW: Nimm Dir mal das Buch von K&R und lerne erst einmal, denn Dir
fehlen noch viele Grundlagen. Erst wenn Dir klar ist, was Du eigentlich
machst (Pointer und so Sachen), dann wirst Du auch ein einges, positives
Ergebnis bekommen.
Ein guter Compiler zum üben unter Windoof ist:
http://www.cs.virginia.edu/~lcc-win32/
Der ist sehr gut zu bedienen und die gesamte Doku ist dabei.
Und er ist für Lau!
Lars schrieb:> Wenn ich string[100] schreibe gehts.
Und wenn du den exakten Code von mir nimmst, geht es nicht? In dem
Fall stimmt irgendwas mit deinem Compiler nicht, oder er ist extrem
veraltet. Oder hast du's nur in deinem Programm probiert? Dann gilt
immer noch:
Rolf Magnus schrieb:> Sinnvoll ist es deshalb, ein minimales, aber vollständiges> Programm zu posten, das den Fehler noch enthält.> Wie kompilierst du mit gcc?
gcc datei.c -o datei
Die habe ich gar nicht konfiguriert.
So sieht es bei mir aus:
struct termios port_settings; // structure to store the port
settings in
cfsetispeed(&port_settings, B300); // set baud rates
cfsetospeed(&port_settings, B300);
port_settings.c_cflag |= PARENB; // setze 7E1
port_settings.c_cflag &= ~PARODD;
port_settings.c_cflag &= ~CSTOPB;
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS7;
port_settings.c_lflag = ICANON;
tcsetattr(fd, TCSANOW, &port_settings); // apply the settings to
the port
return(fd);
Lars schrieb:> res = read(fd,(char *)buf,sizeof(buf));>> aber irgendwie kommen da nur ca.9 Zeilen an....Ist das die große des> Hardware Buffers? Wie zeichnet mann denn alles auf in C?
Der Linux-Kernel macht bei einem read()-Syscall keine Garantien, dass
der Buffer gefüllt wird, es wird das rausgereicht, was gerade da ist.
Nur wenn nix da ist wird blockiert (ok, man kann die Datei auch
nonblocking öffnen, dann kommt "nix" zurück).
Wenn man darauf angewiesen ist, dann macht man das mit den
"highlevel"-Funktionen der libc (fread etc.).
Ich habe mal ein winz-Programm angehängt, welches auf eine serielle
Schnittstelle zugreift und die empfangenen Daten auf stdout als Hexdump
ausgibt. Als Bonus wird da auch gezeigt, wie man mit poll() auf das
Vorhandensein von Daten warten kann - hier nutze ich das dafür, dass
nach einer kleinen Pause ein Zeilenumbruch ausgegeben wird, also
typischerweise nach einem Telegramm.
Ich hoffe das hilft weiter.
Viele Grüße,
Simon
@Simon
Nice trick with the polling.
@Lars
I have used this code on an Arduino , and it seems to be ok. For reading
serial responses from an Arduino.
Beitrag "PortableSerialLib - Portable Serial Port Library"
Maybe it should be extended with the poll Simon shows.
I haven't tried it on windows , but used it in hope of a "dual platform"
support.
regards
Karsten - Denmark
@Simon
Muss man ret hier wirklich auf /EAGAIN/prüfen? - Mit der vorigen
Abfrage sollte doch sichergestellt sein, dass Daten vorhanden sind, oder
nicht (immer)?
mar IO schrieb:> Muss man ret hier wirklich auf /EAGAIN/prüfen? - Mit der vorigen> Abfrage sollte doch sichergestellt sein, dass Daten vorhanden sind, oder> nicht (immer)?
Ja, im Prinzip hast Du recht, es sollten Daten verfügbar sein.
Hier ist das ein bischen defensiv programmiert und schützt einen vor
irgendwelchen komischen Situationen mit z.B. kaputten Treibern. Ich weiß
jetzt gerade nicht, ob ich diese Situation schonmal konkret hatte, aber
ich weiß: Wenn read() EAGAIN zurückgibt, dann will ich es nochmal
probieren, insofern teste ich lieber drauf.
Viele Grüße,
Simon
mar IO schrieb:> Muss man ret hier wirklich auf /EAGAIN/prüfen? - Mit der vorigen> Abfrage sollte doch sichergestellt sein, dass Daten vorhanden sind, oder> nicht (immer)?
In der Man-Page steht:
1
BUGS See the discussion of spurious readiness notifications under the
2
BUGS section of select(2).
Und bei select steht dann:
1
BUGS:
2
Under Linux, select() may report a socket file descriptor
3
as "ready for reading", while nevertheless a subsequent
4
read blocks. This could for example happen when data has
5
arrived but upon examination has wrong checksum and is
6
discarded. There may be other circumstances in which a
7
file descriptor is spuriously reported as ready. Thus it
8
may be safer to use O_NONBLOCK on sockets that should not
9
block.
O_NONBLOCK hat er ja wohl schon, aber dann muß man auch auf EAGAIN
prüfen, um das von einem echten Fehler unterscheiden zu können.