empfangen per rs232 seltsames verhalten (nix geht)
-
Hi alle miteinander!
Folgende Situation: In der Schule (also momentan nicht verfügbar) haben wir eine Wetterstation, die alle 10sek Daten über die RS232-Schnittstelle sendet, egal ob jemand empfängt oder nicht. Ich Habe das Protokoll und will nun ein Programm schreiben, dass zuhört und mitschreibt!
Leider gibt es dabei ein paar Probleme. Wenn ich testeshalber mit "dd if=test.dat of=/dev/ttyS1" Testdaten rübersende, erwarte ich folgende Ausgabe:Datenpaket A identifiziert! Humidity: now: 65% max: 80% 12:32 14.9 min: 12% 02:01 01.2
Bekommen tue ich aber garnix. Um sicherzustellen, dass der Sendebuffer auch geflusht wird, habe ich schon mal ein "echo > /dev/ttyS1" hinterher geschickt, passierte aber immer noch nix.
Gemeinerweise funzt aber "(cat /dev/ttyS0 &) && (dd if=test.dat of=/dev/ttyS1) && (echo ^D > /dev/ttyS1)". OK, es werden keine 0 und so gesendet, also die Zeichen, die man nicht sehen kann.
Meine Frage: Warum? Was ist an meinem Code falsch?weathermon.h
#ifndef WEATHERMON #define WEATHERMON #define HI(x) ((int)((x>>4)&0xF)) #define LO(x) ((int)(x&0xF)) class Application { public: Application(int argc, char* argv[]); ~Application(); void Run(void); private: int commport; }; #endif
weathermon.cpp
#include <signal.h> #include <setjmp.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> #include <string> #include "weathermon.h" Application::Application(int argc, char* argv[]) { // verarbeite cmd-line std::string cport = "/dev/ttyS0"; for(int i=1; i<argc; ++i) { if(strcmp(argv[i], "-c") == 0) cport = argv[++i]; } // configure rs232-connection commport = open(cport.c_str(), O_RDONLY | O_NOCTTY | O_NDELAY); fcntl(commport, F_SETFL, 0); termios options; tcgetattr(commport, &options); cfsetispeed(&options, B9600); options.c_cflag |= (CLOCAL|CREAD); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; tcsetattr(commport, TCSANOW, &options); } Application::~Application() { printf("Bye!\n"); close(commport); } void Application::Run(void) { char id, data[36]; while(1) { switch(read(commport, &id, 1)) { case ((31<<3)|0)&0xFF: // 1111 1000 printf("Datenpaket A identifiziert!\n"); read(commport,data+2, 34); // data[2] == 2. gesendetes byte printf("Humidity: now: %i%i%%\n", LO(data[21]), HI(data[21])); printf("max: %i%i%% %i%i:%i%i %i%i.%i\n", LO(data[22]), HI(data[22]), LO(data[24]), HI(data[24]), LO(data[23]), HI(data[23]), LO(data[25]), HI(data[25]), HI(data[26])); printf("min: %i%i%% %i%i:%i%i %i%i.%i\n", HI(data[27]), LO(data[26]), HI(data[29]), LO(data[28]), HI(data[28]), LO(data[27]), HI(data[30]), LO(data[29]), LO(data[30])); break; case ((31<<3)|1)&0xFF: // 1111 1001 break; case ((31<<3)|2)&0xFF: // 1111 1010 break; case ((31<<3)|3)&0xFF: // 1111 1011 break; case ((31<<3)|4)&0xFF: // 1111 1100 break; } } } Application* app = 0; jmp_buf jumper; void cleanup(int) { longjmp(jumper, 1); } int main(int argc, char* argv[]) { app = new Application(argc, argv); if(setjmp(jumper) == 0) { signal(SIGTERM, cleanup); signal(SIGABRT, cleanup); try { app->Run(); } catch(std::runtime_error err) { fprintf(stderr, "weathermon: %s\n", err.what()); } catch(...) { fprintf(stderr, "weathermon: undefined error!\n"); } } delete app; return 1; }
-
Da is ein Fehler im Code, der da eigentlich net ist. Durch das rumprobieren mit streams und fread() ist da Mist entstanden. Verhalten ist aber das gleiche!
Statt:switch(read(commport, &id, 1)) {
Das:
read(commport, &id, 1); switch(id) {
Sorry.
-
OK .. nochmal sorry! Ich habe gerade festgestellt, dass es am Testdatensatz lag.
Dennoch habe ich ein Problem: Wenn er zum "read(commport,data+2, 34);" Kommt, und eines von den 34 Bytes ein '\n' ist (was durchaus passieren kann, aber nicht als solches gemeint ist), bricht er mit dem lesen ab.
Kann man ihm irgendwie klarmachen, dass '\n' auch nur eine Zahl ist?
-
Hallo
Das ganze liegt daran das du im Canonical mode bist.
Dieser Mode liest dir Zeilenweise dein Signal ein und da bei /n ein Zeilenende vorliegt hoert er auf.Das es funktioiert, musst den canonical mode ausschalten
ungefaehr so:
options.c_lflag &= ~(ECHO|ICANON); options.c_cc[VMIN]=1; //min. 1 zeichen empfangen options.c_cc[VTIME=]= 0; //kein timer
Das ganze wird auch recht gut im Serial Programing Howto erklaert
http://en.tldp.org/HOWTO/Serial-Programming-HOWTO/index.html
und im Serial Programming Guide for POSIX Operating Systems
http://www.easysw.com/~mike/serial/serial.htmlIch hoffe ich konnte dir damit helfen.
Gruss
C-Snoopy
-
Danke für die Info!
Ich habe sogar schon auf diesen Seiten nachgesehen, doch, da ich lesefaul bin, habe ich einfach nach dem Wort "binary" und dem Teilwort "bin" gesucht. Da ich nicht fündig geworden bin, bin ich mit der Meinung "Wird hier wohl nicht erklärt" davon gegangen. (Memo an mich selbst: "Kreativer beim Suchwortentwickeln werden! (Bloß nicht die Lesefaulheit aufgeben, ist ja viel zu viel Arbeit)")