www.mikrocontroller.net

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


Autor: Franz Schinagl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: René König (king)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Pizzaman (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);

Autor: Franz Schinagl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Franz Schinagl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Blackbird (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: René König (king)
Datum:

Bewertung
0 lesenswert
nicht 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;...

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

BTW: Was ist ein DOS32-Programm?

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.