Forum: PC-Programmierung virtuelle Com ports anders in c++ als echte?


von Arpad (Gast)


Lesenswert?

Hi!

Ich habe grad ein kleines C++ problem.
Ich möchte ein kabel bauen das mir langzeitbelichtung mit einer EOS 
erlaubt. prinzipiell muss ich da nur einen schalter haben der 
angesteuert wird... alles kein problem.
Das ansteuern geht über RTS eines seriellen ports.
Nun hab ich mir aus der MS Hilfe mal eine kleine routine kopiert die die 
ports öffnet, und (da noch kein kabel) mit einem multimeter die pins 
gemessen. Im geschlossenen betrieb haben die Pins bei dem echten com1 
eine spannung von ~ -11V. Ist der Port offen, sind es 11V. Das programm 
hab ich gestestet und es funktioniert. Nun aber das problem. Da ich das 
am Notebook machen will, und dieses weder seriell noch parallel hat, 
muss ich einen USB -> Seriell adapter dazwischen schalten. Dafür nehme 
ich den ELV UR - 100. Alles wieder verdrahtet zeigt mir im geschlossenen 
zustand -8.2V. Allerdings lässt sich der port mit dem selben c++ code 
nicht öffnen.
Treiber sind installiert, im geräte manager wird mir auch ein neuer com 
port 3 angezeigt. Aber der Port geht einfach nicht auf.
Mit einer speziellen software die auch dafür geschrieben wurde, klappt 
das, nur hab ich den code dieser software nicht, und will diese auch 
nicht benutzen. Das zeigt aber, aber die hardware in ordnung ist.
Nun, muss ich beim ansprechen eines virtuellen ports irgendwas anders 
machen?

hier der code, falls daraus was ersichtlich wird.

DCB dcb;
   HANDLE hCom;
   BOOL fSuccess;
   TCHAR *pcCommPort = TEXT("COM3");

   hCom = CreateFile(
                  pcCommPort,
                    GENERIC_WRITE,
                    0,    // must be opened with exclusive-access
                    NULL, // default security attributes
                    CREATE_ALWAYS, // must use OPEN_EXISTING
                    1,    // not overlapped I/O
                    NULL  // hTemplate must be NULL for comm devices
                    );

   if (hCom == INVALID_HANDLE_VALUE)
   {
       // Handle the error.
       printf ("CreateFile failed with error %d.\n", GetLastError());
       return (1);
     getchar();
   }
   // Build on the current configuration, and skip setting the size
   // of the input and output buffers with SetupComm.

   SecureZeroMemory(&dcb, sizeof(DCB));
   dcb.DCBlength = sizeof(DCB);
   fSuccess = GetCommState(hCom, &dcb);
   if (!fSuccess)
   {
      // Handle the error.
      printf ("GetCommState failed with error %d.\n", GetLastError());
      return (2);
   }

// Fill in DCB: 57,600 bps, 8 data bits, no parity, and 1 stop bit.
   dcb.BaudRate = CBR_57600;     // set the baud rate
   dcb.ByteSize = 8;             // data size, xmit, and rcv
   dcb.Parity = NOPARITY;        // no parity bit
   dcb.StopBits = ONESTOPBIT;    // one stop bit
   fSuccess = SetCommState(hCom, &dcb);

   if (!fSuccess)
   {
      // Handle the error.
      printf ("SetCommState failed with error %d.\n", GetLastError());
      return (3);
   }
   _tprintf (TEXT("Serial port %s successfully reconfigured.\n"), 
pcCommPort);

ich muss dazu sagen, das ich mich im bereich hardwareansteuerung nicht 
wirklich auskenne, daher hab ich das von MS einfach nur kopiert und dann 
getestet obs läuft oder nicht.
thx.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

"Der Port geht einfach nicht auf" - was ist denn der Fehlercode, den 
CreateFile zurückgibt?

Es gibt -von der Seite der Programmierung her- keinen Unterschied 
zwischen "virtuellen" seriellen Schnittstellen und "echten".

Zumindest beim Überfliegen sehe ich im Code keine großen Probleme - 
allenfalls, wenn eine Schnittstelle mit einer Nummer größer 9 im System 
angesprochen werden soll, muss eine andere Syntax für den Gerätenamen 
verwendet werden -> "\\.\COM10" anstelle von "COM10". Aber das ist schon 
seit weit über einem Jahrzehnt in der Dokumentation von CreateFile 
beschrieben ...

von Christian R. (supachris)


Lesenswert?

Ich würde die DCB nicht löschen. Kann sein, dass du nicht alle Parameter 
setzt dann. Nimm sie wie sie ist und ändere nur deine Parameter.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Das tut er.
1
   SecureZeroMemory(&dcb, sizeof(DCB));   // 1
2
   dcb.DCBlength = sizeof(DCB);           // 2
3
   fSuccess = GetCommState(hCom, &dcb);   // 3



Zwar wird die Struktur in (1) nullinitialisiert angelegt, aber in (2) 
wird sie korrekt initialisiert und in (3) werden die aktiven Werte 
daraus kopiert.

Das ist die korrekte Art des Umgangs mit dieser Struktur.

von Arpad (Gast)


Lesenswert?

@Rufus
Es gibt keine fehler meldung. Das Programm wird bis zur Ausgabe "Port 
has been reconfigured" etc. abgearbeitet, und ended wie es soll, ohne 
irgendeine fehlermeldung. Der Port geht einfach nur nicht auf (was ich 
halt daran sehe das ich zwischen pin 5 und 7 keine spannungsänderung 
messen kann)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dann funktioniert alles.

Solange Du nicht explizit dafür sorgst, daß auf den Handshakeleitungen 
etwas geschieht, wird auf ihnen auch nichts geschehen.

Es gibt mehrere Arten, dafür zu sorgen, daß etwas auf den 
Handshakeleitungen geschieht:

- Im Gerätemanager bei den Eigenschaften der jeweiligen Schnittstelle 
die "Hardwareflussteuerung" aktivieren
(das wird bei Deiner USB-Seriell-Schnittstelle nicht aktiviert sein, bei 
den onboard-Schnittstellen aber schon)

- "von Hand" an den Handshakeleitungen klappern
(das geht mit beispielsweise mit EscapeCommFunction(hSerial, SETDTR))

- im DCB einstellen, daß die Hardwarehandshakeleitungen auch genutzt 
werden sollen
(dafür sind die Elemente fOutxCtsFlow, fOutxDsrFlow, fDtrControl, 
fRtsControl etc. zuständig)

Ersteres ist zunächst am einfachsten, aber am unzuverlässigsten. Deine 
Anwendung sollte, wenn sie denn wirklich Hardwarehandshake benötigt, 
sich auch selbst darum kümmern, den zu aktivieren.

von Arpad (Gast)


Lesenswert?

Aber an meinem Com1 ist die hardwareflusssteuerung auch nicht aktiv, und 
trotzdem wird der port geöffnet wenn ich an dem "echten" port messe.


Aber danke! :)
Hab mal nach RTScontrol gegoogelt und ein simples dcb.fRtsControl = 
RTS_CONTROL_ENABLE; führt zum korrekten öffnen des ports :)
thx!

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.