Forum: PC-Programmierung Abfrage der Signale CTS/DSR unter Win32 (XP)


von Franz Schinagl (Gast)


Lesenswert?

Hallo

Kann mir bitte jemand sagen, wie man unter WindowsXP die Signale CTS
und DSR einer seriellen Schnittstelle (COMx) abfragen kann?

Ich habe schon tief in der MSDN gerumgegraben und Kollegen konsultiert,
aber ich finde einfach nichts.

Es gibt zwar die Möglichkeit abzufragen, ob ein Write durch CTS oder
DSR blockiert wird, aber ich finde nichts, wie ich einfach den Zustand
(High/Low) der beiden Leitungen abfragen kann.

Für entsprechend zielführende Hinweise bedanke ich mich schon im Voraus
ganz herzlich.

Gruß
Franz

von René K. (king)


Lesenswert?


von Pizzaman (Gast)


Lesenswert?

Mit dem .Net 2.0 Framework ganz einfach mit Portname.DsrHolding bzw
Portname.CtsHolding.

Beispiel mit VC# Express:

if (serialPort1.DsrHolding)
            {
                MessageBox.Show("DSR aktiv!", "RS232",
MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else MessageBox.Show("DSR inaktiv!", "RS232",
MessageBoxButtons.OK, MessageBoxIcon.Information);

von Franz Schinagl (Gast)


Lesenswert?

Danke sehr!

Über diese Funktion bin ich in der Hilfe schon gestolpert, konnte aber
auf Grund der bescheidenen Beschreibung und des komischen Namens nichts
damit anfangen. Schließlich interessiert mich kein Modemstatus, wenn ich
garkein Modem angeschlossen habe ;-))

Vielen dank nochmal.
Gruß
Franz

von Franz Schinagl (Gast)


Lesenswert?

Hi

Auch an Pizzaman - danke :)

Ich bin hier leider in einer C++ Umgebung (drunter und drüber), aber
ich werde die C# Variante im Hinterkopf behalten.

Gruß
Franz

von Blackbird (Gast)


Lesenswert?

C++ oder C ist vollkommen egal. Den COM-Port fragt man mit
API-Funktionen ab. Nur ist die Frage gestattet, ob Du im Polling oder
ereignisgesteuert abfragen willst?

Polling geht so (hier gleich mit Setzen der Ausgaenge):

/*******************************************
**    Nur Demo der Funktionen
**
** Button an RTS und CTS anschließen:
** An RTS wird Spannung gelegt ("ON"), CTS liest
** noch "LOW", solange der Button nicht gedrückt
** wird.
**
** RTS (Ausgang): Pin7 ist +10V (== AUS)
**                Pin7 ist -10V (== EIN)
** CTS (Eingang): Pin8 wird abgefragt
*******************************************/
#include <windows.h>

int main (void)
{
  HANDLE hPort;
  DWORD  CtsStatus;

  // COM1 öffnen:
  hPort =  CreateFile (TEXT("COM1"), GENERIC_READ | GENERIC_WRITE,
                       0, NULL, OPEN_EXISTING, 0, NULL);

  EscapeCommFunction (hPort, SETRTS); // RTS setzen (= -10V = ON)
  //EscapeCommFunction (hPort, CLRRTS); // rücksetzen geht so

  // Button abfragen:
  GetCommModemStatus (hPort, &CtsStatus);

  if ((CtsStatus & MS_CTS_ON))
  {
    // irgendwas machen wenn Button gedrückt wurde ...
  }

  // ...

  CloseHandle (hPort);
  return 0;
}




und Ereignisgesteuert geht so (in Klassen packen kannst Du alleine?):

/**********************************************************************
** Testprogramm: Wartet auf eine Pegeländerung an DSR, CTS, ... an
COM1
**
** Getestet: OK ab 12/2002!
**********************************************************************/

#include <windows.h>
#include <stdio.h>

#define TIMELIMIT 100000   // Programm läuft 100 Sekunden

// zusätzliche Events (DDK)
#define SERIAL_EV_RXCHAR           0x0001  // Any Character received
#define SERIAL_EV_RXFLAG           0x0002  // Received certain
character
#define SERIAL_EV_TXEMPTY          0x0004  // Transmitt Queue Empty
#define SERIAL_EV_CTS              0x0008  // CTS changed state
#define SERIAL_EV_DSR              0x0010  // DSR changed state
#define SERIAL_EV_RLSD             0x0020  // RLSD changed state
#define SERIAL_EV_BREAK            0x0040  // BREAK received
#define SERIAL_EV_ERR              0x0080  // Line status error
occurred
#define SERIAL_EV_RING             0x0100  // Ring signal detected
#define SERIAL_EV_PERR             0x0200  // Printer error occured
#define SERIAL_EV_RX80FULL         0x0400  // Receive buffer is 80
percent full
#define SERIAL_EV_EVENT1           0x0800  // Provider specific event
1
#define SERIAL_EV_EVENT2           0x1000  // Provider specific event
2

// Prototypes
const char* decimalToBinary (const long value,
                             const unsigned length,
                             char* pszBuffer);

/********************************************************************
** DOS32-programm läuft TIMELIMIT / 1000 Sekunden und zeigt alle
** Pegeländerungen an COM 1 an
********************************************************************/
int main (void)
{
  HANDLE hCom;
  OVERLAPPED o;
  DWORD dwStart;
  DWORD dwEvtMaskIn = EV_CTS | EV_DSR | EV_BREAK | EV_RING | EV_RXCHAR |

                      EV_RLSD | EV_ERR | EV_RXFLAG | EV_TXEMPTY |
                      SERIAL_EV_PERR | SERIAL_EV_RX80FULL |
                      SERIAL_EV_EVENT1 | SERIAL_EV_EVENT2;
  DWORD dwEvtMask = 0;
  char szString[] = ("\r\nWarte auf Events (Pegelaenderungen) an COM
1:\r\n\
EV_RXCHAR  =0x%04x\r\nEV_RXFLAG  =0x%04x\r\nEV_TXEMPTY
=0x%04x\r\n\
EV_CTS     =0x%04x\r\nEV_DSR     =0x%04x\r\nEV_RLSD
=0x%04x\r\n\
EV_BREAK   =0x%04x\r\nEV_ERR     =0x%04x\r\nEV_RING
=0x%04x\r\n\
EV_PERR    =0x%04x\r\nEV_RX80FULL=0x%04x\r\nEV_EVENT1
=0x%04x\r\n\
EV_EVENT2  =0x%04x");
  char szBuf[sizeof (DWORD) * 8] = "";  // für
decimalToBinary-Funktion
  SYSTEMTIME    SystemTime;   // system time
  TCHAR         lpszMsg[127] = "";


  printf (szString, EV_RXCHAR, EV_RXFLAG, EV_TXEMPTY,
      EV_CTS, EV_DSR, EV_RLSD, EV_BREAK, EV_ERR, EV_RING, 
SERIAL_EV_PERR,
      SERIAL_EV_RX80FULL, SERIAL_EV_EVENT1, SERIAL_EV_EVENT2);

  hCom = CreateFile ("COM1",
    GENERIC_READ | GENERIC_WRITE,
    0,    // exclusive access
    NULL, // no security attributes
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    NULL);

  if (hCom == INVALID_HANDLE_VALUE)
    return printf ("\r\nCOM1 kann nicht geöffnet werden");

  if (!SetCommMask (hCom, dwEvtMaskIn))
    return printf ("\r\nSetCommMask fehlgeschlagen");

  // Create an event object for use in WaitCommEvent.
  o.hEvent = CreateEvent (
    NULL,   // no security attributes
    FALSE,  // auto reset event
    FALSE,  // not signaled
    NULL);  // no name

  dwStart = GetTickCount ();

  while (GetTickCount () - dwStart < TIMELIMIT)
  {
    WaitCommEvent (hCom, &dwEvtMask, &o);

    if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE))
    {
      GetLocalTime (&SystemTime);
      printf ("\r\nEvents: %s - ", decimalToBinary (dwEvtMask, sizeof
(DWORD) * 8, szBuf));

      if (dwEvtMask & EV_DSR)
        printf ("DSR ");

      if (dwEvtMask & EV_CTS)
        printf ("CTS ");

      if (dwEvtMask & EV_BREAK)
        printf ("BREAK ");

      if (dwEvtMask & EV_RING)
        printf ("RING ");

      if (dwEvtMask & EV_RXCHAR)
        //printf ("RXCHAR ");
      if (dwEvtMask & EV_RLSD)
        printf ("RLSD ");

      if (dwEvtMask & EV_ERR)
        printf ("ERR ");

      if (dwEvtMask & EV_RXFLAG)
        printf ("RXFLAG ");

      if (dwEvtMask & EV_TXEMPTY)
        printf ("TXEMPTY ");

      if (dwEvtMask & SERIAL_EV_PERR)
        printf ("PERR ");

      if (dwEvtMask & SERIAL_EV_RX80FULL)
        printf ("RX80FULL ");

      if (dwEvtMask & SERIAL_EV_EVENT1)
        printf ("EVENT1 ");

      if (dwEvtMask & SERIAL_EV_EVENT2)
        printf ("EVENT2 ");

      wsprintf (lpszMsg, "%s, den %02d.%02d.%04d um %d:%d Uhr %d,%d
Sek.",
        SystemTime.wDayOfWeek == 1 ? "Mo" :
        (SystemTime.wDayOfWeek == 2 ? "Di" :
        (SystemTime.wDayOfWeek == 3 ? "Mi" :
        (SystemTime.wDayOfWeek == 4 ? "Do" :
        (SystemTime.wDayOfWeek == 5 ? "Fr" :
        (SystemTime.wDayOfWeek == 6 ? "Sa" :
        (SystemTime.wDayOfWeek == 7 ? "So" : "Heute")))))),
        SystemTime.wDay, SystemTime.wMonth, SystemTime.wYear,
        SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond,
        SystemTime.wMilliseconds);
      printf (": %s", lpszMsg);
    }
  }

  CloseHandle (o.hEvent);
  CloseHandle (hCom);

  return printf ("\r\n!ENDE! %d Sekunden sind um!\r\n", TIMELIMIT
/ 1000);
}


/*********************************************************************** 
******
** Umwandlung: Dezimal zu Binär
**
** 1. Param: die Zahl
** 2. Param: Anzahl der Binärstellen (von 1..32)
** 3. Param: Zeiger auf ein char-Array, das den String aufnehmen kann
************************************************************************ 
*****/
const char* decimalToBinary (const long value,
                             const unsigned length,
                             char* pszBuffer)
{
  if ((length == 0) || (length > 32))
  {
    pszBuffer = '\0';
    return pszBuffer;
  }

  unsigned digit = 1 << (length - 1);
  char* pszCurrent = pszBuffer;

  do
  {
    if (value & digit)
      *pszCurrent = '1';
    else
      *pszCurrent = '0';
    pszCurrent++;
    digit /= 2;
  } while (digit != 0);

  *pszCurrent = '\0';

  return pszBuffer;
}

Blackbird

von René K. (king)


Lesenswert?

> // COM1 öffnen:
>   hPort =  CreateFile (TEXT("COM1"), GENERIC_READ | GENERIC_WRITE,
>                       0, NULL, OPEN_EXISTING, 0, NULL);

Das würde so nicht machen, auch wenn es in diesem speziellen Fall
funktioniert. Früher oder später handelst Du Dir mit diesem Vorgehen
Probleme ein. Richtig sieht das so aus:

hPort =  CreateFile (TEXT("\\\\.\\COM1"), GENERIC_READ |
GENERIC_WRITE,
                     0, NULL, OPEN_EXISTING, 0, NULL);

Siehe auch KB115831,
http://support.microsoft.com/default.aspx?scid=kb;en-us;115831

Aber hatte sich das eigentliche Problem nicht schon vor zwei Tagen
gelöst?

BTW: Was ist ein DOS32-Programm?

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.