Startseite

PC-Programmierung der seriellen Schnittstelle

Hier möchte ich kurz darstellen, wie die serielle Schnittstelle unter Linux und unter Windows programmiert wird. Das ist insbesondere dann wichtig, wenn man sich mit der Kommunikation nicht nur auf ein paar Bytes beschränken möchte wie man es man hterm gut machen kann.

Will man hingegen die serielle Schnittstelle verwenden, um den Controller für Mess- oder Steuerungsaufgaben einzusetzen, so muss man die serielle Schnittstelle am PC selbst programmieren.

Im Wesentlichen ist die Vorgehensweise unter Linux oder unter Windows gleich.

  1. Die serielle Schnittstelle bekommt vom Betriebssystem einen Gerätenamen zugewiesen.
  2. Die serielle Schnittstelle wird unter dem Gerätenamen geöffnet mit dem entsprechenden Bfehel des Betriebssystems.
  3. Die serielle Schnittstelle wird konfiguriert.
  4. Zur Kommunikation werden nun die Standard-Befehle des Betriebssystems eingesetzt.
  5. Wenn die Kommunikation abgeschlossen werden soll, dann wird das Gerät wieder geschlossen mit dem entsprechenden Befehl des Betriebssystems.

Das alles sollte jedem Programmierer geläufig sein bis auf die Konfiguration der seriellen Schnittstelle.

Programmierung der Schnittstelle unter Linux

Der folgende Code-Schnipsel zeigt das Prinzip, wie die serielle Schnittstelle unter Linux angesprochen wird.

Beispiel

int fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY);

struct termios config;
tcgetattr(fd, &config);

        /* Control mode flags: 8 Bit Wortbreite, keine Parität */
        config.c_cflag &= ~(CSIZE | PARENB | CSTOPB);
        config.c_cflag = CS8 | CLOCAL | CREAD;

        /* Local mode flags: kein Echo, keine Signallisierung */
        config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

        /* Input mode flags: keine Software FLowcontrol */
        config.c_iflag &= ~(IXON | IXOFF | IXANY);

        /* Output mode flags: kein Postprocessing */
        config.c_oflag = &= ~OPOST;

        /* Beim Lesen kann jede beliebige Anzahl von Zeichen von der Schnittstelle gelesen werden */
        config.c_cc[VMIN] = 0;

        /* Timeout beim blockierenden Lesen (in hundertstel Sekunden) */
        config.c_cc[VTIME] = 5;

        /* Baudrate */
        cfsetspeed(&config, B9600);

tcsetattr(fd, TCSAFLUSH, &config);

/* Zeichen aus einem Buffer auf die serielle Schnittstelle schreiben */
unsigned char *buffer;
int bytesWritten = write(fd, buffer, bytesToWrite);
 
/* Zeichen von der serielle Schnittstelle auslesen */
int bytesRead = read(fd, buffer, bytesToRead);

close(fd);

Die folgende ZIP-Datei enthält die C++ Klasse BlockingCommPort. Diese basiert auf obigen Code-Beispiel und fügt noch Fehlerbehandlung und außerdem noch den Port-Namen und die Baudrate als Parameter hinzu.

Programmierung der Schnittstelle unter Windows

Unter Windows sieht es fast genau so aus wie unter Linux.

Beispiel

HANDLE hComm = CreateFile("COM1", , GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);

DCB dcb;
ZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
GetCommState(hComm, &dcb);

    /* Baudrate */
    dcb.BaudRate = CBR_9600;

    /* 8-Bit Wortlänge */
    dcb.ByteSize = 8;

    /* keine Parität */
    dcb.Parity   = NOPARITY;

    /* ein Stopp-Bit */

    dcb.StopBits = ONESTOPBIT;   
SetCommState(hComm, &dcb);

COMMTIMEOUTS commTimeouts = { 10, 10, 10, 10, 10 };
SetCommTimeouts(hComm, &commTimeouts);

/* Zeichen aus einem Buffer auf die serielle Schnittstelle schreiben */
unsigned char *buffer;
WriteFile(hComm, buffer, bytesToWrite, &bytesWritten, 0);
 
/* Zeichen von der serielle Schnittstelle auslesen */
ReadFile(hComm, buffer, bytesToRead, &bytesRead, 0);

CloseHandle(hComm);