mikrocontroller.net

Forum: PC-Programmierung Seriellport im PC lesen/ schreiben


Autor: D.M (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.

Ich weiß nicht wie ich unter C den RS232 Port lesen/schreiben soll.
Ich hab keine Ahnung was es da für Befehle gibt und was die machen.

Ich hab vor Daten von meinem Atmega16 an den PC zu senden.

Kann mir da jemand helfen?

Autor: Jan H. (zool)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Reihe nach

CreateFile("COM1:",...    // Port öffnen

GetCommState    // vorbereiten der Schnittstellenparameter, spart den 
kompletten DCB selbst zu bauen

SetCommState    // angepasste Werte aktivieren (Baudrate, Stopbits,...)

ReadFile / WriteFile    // die eigentliche Datenübertragung

CloseHandle   // das wars  ;-)


Hoffe Du hast die MSDN-CD's installiert. Da gibts dann nähere Infos zu. 
Falls nicht: http://msdn.microsoft.com

Autor: Jan H. (zool)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach so, schon Windows, oder??  ;-)

Autor: Weinga-Unity (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Kuck mal hier:
http://pvbrowser.org/pvbrowser/sf/manual/rllib/htm...

Download des Ganzen:
http://pvbrowser.de/pvbrowser/tar/rllib.tar.gz

Funktioniert super. Musst halt all jene Dateien mit in dein Projekt 
mitnehmen, nach denen der Compiler schreit.

mfg W.K.

Autor: D.M (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Jan H.

Könntest du mir vielleicht ein beispiel geben?

Autor: Frank (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo Jan, schon schlimm einfach so ein paar Brocken hinzuwerfen wo der 
Kumpel doch gern ein komplettes Programm gehabt hätte...

Autor: Jan H. (zool)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du wolltest doch die Befehle wissen, die man für serielle Kommunikation 
unter Windows braucht?! Das sind sie - mehr ist da nicht (ok, ein, zwei 
Sachen gibts da noch, aber für Deinen Zweck reicht das).
Du brauchst im einfachsten Fall genau diese Funktionen in dieser 
Reihenfolge.

Mach MSDN auf, lokal oder online und schau Dir die genaue Syntax an. Ein 
komplettes Beispiel kann ich Dir nicht geben - und würde Dir auch nicht 
viel bringen, weil der eigentliche Kommunikationsteil ja nur einen 
kleinen Teil der Programme ausmacht.

Ach ja, Get-/SetCommTimeouts hatte ich noch vergessen. Ist wichtig um 
ein definiertes Timing zu erhalten.

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und ReadFile sollte in einem eigenen Thread stehen und mit WaitCommEvent 
und WaitForSingleObject auf ein Read- oder sonstiges Ereignis am Port 
warten.
Sonst hilft nur pollen im main thread.

HyperTerminal tut's aber auch, ganz ohne programmieren.

Blackbird

Autor: Feadi F. (feadi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Blackbird:
WaitForSingleObject kenn ich, aber welche Funktionen braucht man dafür:
> Sonst hilft nur pollen im main thread.
?

Gruß, Feadi

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pollen:
Am Anfang die Timeouts einstellen, z.B.: so:
  COMMTIMEOUTS  ct;
  GetCommTimeouts (hCom, &ct);
  // Warte-Zeit [ms] vom Beginn eines Bytes bis zum Beginn des nächsten Bytes 
  ct.ReadIntervalTimeout         = 1000 / BAUDRATE * (dcb.ByteSize + 
                                                     (dcb.Parity == NOPARITY ? 0 : 1) + 
                                                     (dcb.StopBits == ONESTOPBIT ? 1 : 2)) * 2;
  ct.ReadTotalTimeoutMultiplier  = 0;  // [ms] wird mit Read-Buffer-Size multipliziert
  ct.ReadTotalTimeoutConstant    = 50; // wird an ReadTotalTimeoutMultiplier angehängt
  ct.WriteTotalTimeoutMultiplier = 0;
  ct.WriteTotalTimeoutConstant   = 0;
  SetCommTimeouts (hCom, &ct);

Ja, und dann in einer Schleife immer ReadFile aufrufen.

Das ist aber die schlechteste Variante, besser ist ein eigener Thread 
(CreateThread), in dem man auf ein Read-Ereignis am Port wartet und dann 
erst ReadFile aufruft. Weil ja dann auch ein Byte angekommen ist.

Zuerst wird eine Overlapped-Struct erstellt und mit einem Event 
verknüpft.
  OVERLAPPED    o;
  memset (&o, 0, sizeof (OVERLAPPED)); // Struktur mit 0en füllen
  o.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); // einen Event setzten

dann eine Maske mit den Events, af die man warten möchte und eine, die 
die eintreffenden Events aufnimmt, erstellt:
  DWORD         dwSetMask = EV_RXCHAR | EV_ERR; 
  DWORD         dwEvtMask; 

und dann wird in einer Endlosschleife auf die Events gewartet:
  do  // in Endlos-Schleife auf Empfangssignale warten:
  {
    WaitCommEvent (hCom, &dwEvtMask, &o); // Event mit Empfangssignalen verknüpfen

    if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE)) // warten bis Event
    {
      if (dwEvtMask & EV_RXCHAR) // Zeichen an RxD empfangen:
      {
        bRet = ReadFile (hCom, &InString, sizeof (InString), &dwRead, NULL);
...
      if (dwEvtMask & EV_ERR) // Zeichen an RxD empfangen:
      {
     ...


Naja, das Übliche mit DCB, Fehlerauswerten, Sende- und Empfangspuffer 
setzen, Schließen von Thread und COm und Event usw. nicht vergessen.

Schreiben kann man aus jedem Thread heraus, sollte nicht im 
Empfangsthread sein und wenn möglich, in einem eigenen Thread ablaufen, 
wel man so ganz bequem feststellen kann, ob die Zeichen auch wirklich 
raus sind (an den Treiber) und nicht der Puffer noch voll ist und man 
Zeichen überschreibt.

Für das Öffnen, Schließen und Setzen der seriellen Ports und der 
einzelnen Pins gibts es massig C/C++ -Code-Schnipsel und -Klassen. Aber 
keine mir bekannte behandelt das Empfangen in einem Thread. Es wird 
immer nur eine schön eingepackte ReadFile-Routine vorgestellt, aber wo 
soll man die aufrufen?


Blackbird

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vor Aufruf der do-while-Schleife kommt noch das Setzen der Maske:
  SetCommMask (hCom, dwSetMask); // Empfangssignale definieren

Hatte ich vergessen.

Blackbird

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch'n Zusatz, zum Pollen:

Den Code für den Empfangsthread kann man auch in den main-Thread packen 
und statt INFINITE in WaitForSingleObject eine Wartezeit angeben. Auf 
einen Event braucht man dann aber nicht warten.

Blackbird

Autor: Feadi F. (feadi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Danke für die Erklärung!
Das probiere ich bei Gelegenheit gleich mal aus.

Gruß, Feadi

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Blackbird wrote:

> Für das Öffnen, Schließen und Setzen der seriellen Ports und der
> einzelnen Pins gibts es massig C/C++ -Code-Schnipsel und -Klassen. Aber
> keine mir bekannte behandelt das Empfangen in einem Thread. Es wird
> immer nur eine schön eingepackte ReadFile-Routine vorgestellt, aber wo
> soll man die aufrufen?

Doch, bei CodeGuru: 
http://www.codeguru.com/Cpp/I-N/network/serialcomm...

Funktioniert wunderbar, nehme ich in leicht erweiterter Form auch immer. 
Ich hab mir noch Binärdatentransfer und das ordentliche Schließen der 
Schnittstelle sowie Behandlung der COM bis 255 hinzugefügt.

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.