mikrocontroller.net

Forum: PC-Programmierung RS232 über C++ auslesen


Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Folgendes Problem:

Ich sende mit einzelne Byte's mit meinem µC über RS232 an den PC. Ich
möchte die Daten der RS232 mit einem C++  auslesen und im Programm
damit weiterrechnen.
Ich hab im Internet schon verzweifelt nach brauchbaren Infos gesucht,
leider ohne Erfolg. Entweder, der Code ist fehlerhaft oder in einzelne
Stücke zerhackt und schlecht erklärt.
Ich habe bisher keine Erfrahrung über Schnittstellenprogrammierung in
C++.

Was nützlich wäre:
-Links  wo dieses Thema ausführlich erklärt wird
-Bücher " "
- Quellcode der funktioniert und erklärt ist

MfG
Johannes

Autor: Hubert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht mal die Suchfunktion benutzen...
www.codeguru.com
www.codeproject.com

Autor: Helge Dietert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja mit Linux kannst du einfach das entsprechende Device ( meist
/dev/ttySx ) öffenen und es dann wie eine normale Datei behandeln.
Musst natürlich die Rechte und so passend setzen!

Autor: Tobi H. (tobi-) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Kai Klenovsek (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ferig und leicht zu nutzen:
http://kk.elektronik-4u.de/index.php?Sid=14

Autor: Tobi H. (tobi-) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fertig zum nutzen und nicht nur als DLL verfügbar:
http://www.iftools.com/ctb.de.html

(so ziemlich die beste Lib, die ich kenne. Sogar für Win und Linux
geeignet!)

Autor: Karlheinz Druschel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leuts, ich habe auch mal ne Frage dazu, will aber nicht den 100.
Thread dazu beginnen :-)

Mein PC soll via RS232C mit einem Gerät kommunizieren.
Beispielsweise schicke ich den String "R0.29.0 + <CR>".
Das Teil antwortet mit "<CR><LF>V29.1234<CR<>LF>

Problem:
Via Hyperterminal funzt das alles (9600,n,8,1, kein Handshake).
Via C++ (Beispiele aus dem Net, aus den genannten Verweisen...) wird
IMMER nur ein "r" gelesen
Woran kann das liegen ?

Greets
Karlheinz

Autor: Karlheinz Druschel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klar, woran es liegt weiss ich jetzt:
Das gerät sendet ja jedes empfangene Zeichen als Echo zurück!
Das kann ich auch nicht abschalten, ist ja nicht mein Gerät.
Wie programmiert man sowas ? Zeichen für Zeichen ausgeben, zurücklesen,
vergleichen und dann nächstes Zeichen schicken ?

Wer hat denn Erfahrung bei sowas ?


Greets
Karlheinz

Autor: Tobi H. (tobi-) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder gleich den ganzen String ausgeben und danach die Anzahl der
gesendeten Zeichen wieder einleisen, bei Bedarf kann man auch
vergleichen, wenn das wirklich nötig ist. Zeichen für Zeichen halt ich
für übertrieben. Die Schnittstelle am PC hat grosse Puffer

Autor: Karlheinz Druschel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau hier sitzt mein Problem:
Wennich 10 Zeichen schreibe und versuche dann was zu lesen, dann
behauptet er nur ein Zeichen gelesen zu haben.Nämlich das erste.
Wenn ich 1 Byte schreibe, dann lese, dann schreibe.... funzt es.
Ein Terminalprogramm macht ja auch genau das.
Aus mir unerklärlichen Gründen kriege ich immer nur ein Zeichen
ausgelesen

Autor: Tobi H. (tobi-) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, ein Terminalprogramm liest meines Wissens nach auch blockweise,
schon der Geschwindigkeit wegen (macht meins zumindest so).

Die Frage wäre also, wo gehen die anderen Empfangenen verloren. Kannst
du den relevanten Codeblock hier mal reinstellen?

Autor: Karlheinz Druschel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Klar, die Funktion ist im beigefügten Textfile.
Lt. Doku des angeschlossenen Gerätes muss der Vefehlsstring mit CR
abgeschlossen sein, wobei das CR nicht geechot wird.
Daraufhin antwortet das Gerät mit CR+LF+"V....."+CR+LF
Mit Hyperterminal gehts einwandfrei, mit CPP krieg ich immert nur das
erste Zeichen

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schreiben und gleich darauf einlesen - was ist, wenn das externe Gerät
etwas langsam ist? Dann rattert der PC über die if-Abfrage hinweg.
WaitForSingeObject(...) ist hier die Lösung.

Außerdem fehlt CloseHandle.

Blackbird

Autor: Karlheinz Druschel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wo kriegt man da mal ein Beispiel her ?

CloseHandle fehlt nicht, wird ausgeführt wenn das Fenster geschlossen
wird.

Autor: Tobi H. (tobi-) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probier doch einfach mal vor dem Read eine Pause einzuifügen, nur als
proof-of-concept, ob es wirklich damit dann behoben ist

Autor: Blackbird (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Im Anhang ist ein kleines kommentiertes Beispiel. Ohne Threads. D.h.,
das Programm wartet auf ein Ereignis am COM-Port. Wenn jedoch während
des Wartens weitergearbeitet werden soll, so muß mit Threads gearbeitet
werden.

Blackbird

Autor: Karlheinz Druschel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da habe ich wenigstens einen Anhaltspunkt, 1000 Dank


Greets
Karlheinz

Autor: Karlheinz Druschel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na also, irgendwie klappts ja jetzt sogar.
Nur eine Frage hätte ich noch:
Die Werte für Timeouts werden ja gesetzt, aber nie irgendwie abefragt.
Wird ein Timeout durch ein EV_ERR signalisiert ?

Autor: Tobi H. (tobi-) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, nach der eingestellten Timeout-Zeit bricht der Schreib/Leseversuch
nur ab. Da sorgt dafür, dass die Fnktionen nicht blockieren. EV_ERR
signalisiert Pufferüberläufe, Parity/Frame-Error u.ä

Autor: Karlheinz Druschel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anyway, dank eurer Hilfe habe ich eine grundlegende Kommunikation nun
laufen, den Rest krieg ich schon gebacken.
1000Dank Jungs




Greets
Karlheinz

Autor: Chrisi (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Sers Johannes,
ich hatte vor ein paar Wochen in etwa das gleiche Problem. Viele Leute,
die dir antworten und es gut meinen, jedoch nichts dabei, was dir
wirklcih weiter hilft. Nach etwas Einarbeitung habe ich den Einstieg
geschafft.
Ich würde dir empfehlen auf die MSDN Homepage zu schauen:
Schaue dir dort drei Dinge an: DCB, ReadFile, WriteFile
Mehr brauchst du voerst nicht.
Lies dir diese drei Themen durch und dann kannst du mal den angehängten
Quellcode anschauen.
Damit dieser Sinn macht, verbinde TxD und RxD Leitung und das Programm
wird 5 Bytes senden und 5 Bytes empfangen und sie dir anzeigen. Somit
sollte das wichtigste für dich geschafft sein: Der Einstieg !!!
Anmerkung: Der SourceCode ist sehr kurz gehalten, damit du auch alles
nachvollziehen kannst.
Bitte gib hier kurz bescheid, ob du den Einstieg geschafft hast.
Gruß Christian

Autor: cooper3210 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
Leider Hänge ich am gleichen Problem und komme nicht weiter!!
könnt Ihr mir helfen ?

//////////////////////////////////////////////////////////////
  /////////////include für serial aus dem Internet//////////////
  #include <iostream>
  #include <cstdio>
  #include <fstream>
  #include <sstream>
  #include <cstdlib>
  #include <stdio.h> /* Standard input/output definitions */
  #include <string.h> /* String function definitions */
  #include <unistd.h> /* UNIX standard function definitions */
  #include <fcntl.h> /* File control definitions */
  #include <errno.h> /* Error number definitions */
  #include <termios.h> /* POSIX terminal control definitions */
   /////////////////////////////////////////////////////////////
   using namespace std;
  /////////////////////////////////////////////////////////////
   int fd; // File descriptor Serial
   struct termios options;
   int open_port(void)
  {
      /*                         SETINGS
*/
      /* set raw input, 1 second timeout
       * Set the baud rates to 9600...
       * /dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
       * /dev/ttyS1, UART: 16550A, Port: 0x02f8, IRQ: 3
       * einstellungen mit minicom auf  No parity (8N1): meine
einstellungen
       * UNIX 8N1 meine serial einstellung */
     tcsetattr(fd, TCSANOW, &options);
     options.c_cflag &= ~CRTSCTS;
     cfsetispeed(&options, B9600);// bits pro sek
     options.c_cflag &= ~PARENB;  // noch kein Plan ?
     options.c_cflag &= ~CSTOPB;  // noch kein Plan
     options.c_cflag &= ~CSIZE;   // noch kein Plan
     options.c_cflag |= CS8;      // stop Bits
     options.c_cc[VMIN]  = 0;
     options.c_cc[VTIME] = 10;
    /*                     VERBINDEN
*/
    /* dev/ttyS0  fuer com1    dev/ttyS1 fuer com2 */
      fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);//
öffne()' -  port1
      fcntl(fd, F_SETFL, FNDELAY);
      tcgetattr(fd, &options);

  if (fd == -1)
      {
           // wenn ich denn port nicht öffnen kann
           perror("\nCOM1: ERROR kann Port nicht Öffnen!! /dev/ttyS0
- ");
           printf("\n ACHTUNG PROGRAMM BITTE ALS ROOT
AUSFÜHREN!!\n\n");
      }
       else
      {
           printf("\nVerbindung wurde erfolgreich hergestelle");
           }
            return (fd);
           }

       /*   void close_port()
           {
                close(fd);          //schliesst port soll aber nicht
           }
       */



 ///////////////////// Hauptprogramm //////////////////////////
  int main(int argc, char* argv[])
  {
         int status;
         char retval;
         char buffer[255];
         ssize_t size;
         status=open_port();
         if (status != -1) {
         fcntl(status, F_SETFL, FNDELAY);
             cout << "\n vor while        " << buffer ;//test
             while (size > 0)
                     //oder so !!!!!!!
                     // while(retval!=-1)
                     {
                         cout << "\nvor size     " << buffer ;//test

                         size = read(status, buffer,255);//buffer
leider nur 255 zeichen im mom
                         if (size > 0)
                         {
                                 buffer[size] = '\0';
                                 printf("\n%c", buffer);
                                 cout << "\n nach \n%c         " <<
buffer ;//test
                         }
                       }
             /*close_port();     // port schliessen hört auf zu loogen

               printf("\n\nVerbindung wurde getrennt\n"); */
         }
         ///////////////////////////Ausgabe/in log
datei/////////////////////////
         /* erstellen der log datei */
             ofstream
output("/home/cooper3210/Documents/logger.txt");
             if (!output)
             // Fehler abfangen
             {
                 cout << "Fehler beim Erstellen der Datei!\n";
                 exit (1);
             }
         cout << buffer;  // test
         cout << "\n\n";
         cout << "LOGGER Daten in eine Datei schreiben!!! \n" <<
buffer;
         output << " LOGGER COM 1 " << endl;
         output << buffer << endl;  // buffer in datei schreiben
      ////////////////// Programm ENDE
////////////////////////////////////
         retval=getchar();            // warten auf enter !!!
 }

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Martin Graefe: "C und Linux", ISBN 3-446-22055-0 im Carl Hanser-Verlag
Muenchen.

Leider ist es nicht damit getan, einfach in einem Programm einmal oder
laufend den COM-Port abzufragen. Der Prozess blockiert dann den ganzen
PC. Auch ein Sleep oder usleep oder Timer hilft nicht, weil in der
Wartezeit zwar andere Prozesse drankommen koennen, aber inzwischen auch
der Empfangspuffer ueberlaufen kann.

Deshalb wird unter Windows mit Events gearbeitet (geht auf Interrupts
zurueck) und unter Linux direkt mit Interrupts. Root-Rechte muss nur
das Programm besitzen, nicht gleich der User.

Overlapped braucht man bei Windows nur, wenn man gleichzeitig empfangen
und senden will, denn das Senden kann aus jedem anderen Thread
unabhaengig erfolgen.

Blackbird

Autor: Karlheinz Druschel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also bei mir wars definitiv die Geschwindigkleit.
Das externe Gerät sendet und empfängt zwar mit 9600 baud, aber die Zeit
zwischen den Zeichen war zu kurz.
Da das Messgerät aber die Eigenschaft hat jedes empfangene Zeichen als
Echo zu senden, warte ich einfach nach jedem Byte bis ich das gleiche
Byte wieder empfange.
Nun funzt es.


Greets
Karlheinz

Autor: cooper3210 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo
Also sorry ich sehe nun überhaupt nicht mehr durch ;-)
Ich wollte unter linux nur ein serial monitor haben mit 9600 bis/sek.
Das ganze von mir tut ja schon mal was nur ist dort ein fehler drin
denn ich nicht finden kann.
meine ausgabe  logger.txt schaut meist so aus.
 LOGGER COM 1
R @p  XR @? @

ist nicht viel oder lol!!!!
Das gleiche unter root!
ich denke mal das ist ein problem  bei options.c aber ich komme dort
nicht klar !
laut
http://www.easysw.com/~mike/serial/serial.html#2_5
sollte ich mit minicom mal meine orginal einstellung prüfen was ich
auch habe!
No parity (8N1):
options.c_cflag &= ~PARENB
options.c_cflag &= ~CSTOPB
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
wäre für mich zutreffent ! und ich denke mal da habe ich doch alles
richtig.
Selbst wenn es duch das abfragen mein rechner blockiert sollte in der
ausgabe mehr sein oder ?
cooper<<< nicht mehr klar kommen
DAnke für Eure Hilfe

Autor: cooper3210 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
noch mal ich also ich habe eben gesehen
(((((((""Blackbird """
Root-Rechte muss nur
das Programm besitzen, nicht gleich der User.))))))))

wie soll denn das gehen ??????????
mfg cooper

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Programm mit chmod mit den Zugriffsrechten R, X und S versehen und
mit chown den Benutzer "root" eintragen (alles als root natuerlich).
Dann werden beim Ausfuehren Root-Rechte dem Prozess mitgegeben, auch
wenn man es als Nicht-"root" user ausfuehrt.

Blackbird

Autor: cooper3210 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für diesen Tipp, ist gut das mal zu wissen !!!!!
Cu mfg Cooper

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.