Text über die Serielle Schnittstelle (COM3) einlesen



  • Hallo,
    ich möchte einen Text über die Serielle-Schnittstelle (COM3) einlesen.
    Dazu habe ich hier im Forum folgendes Beispiel gefunden:

    // ConsoleApplication3.cpp : Diese Datei enthält die Funktion "main". Hier beginnt und endet die Ausführung des Programms.
    // Serielle Schnittstelle ansprechen und Daten senden
    // https://www.c-plusplus.net/forum/topic/300637/serielle-schnittstelle-ansprechen-und-daten-senden
    
    
    #include <iostream>
    #include <stdio.h>
    #include "ComPort.h"
    
    ComPort::ComPort(void)
    {
        hCom = INVALID_HANDLE_VALUE;
    }
    
    ComPort::~ComPort(void)
    {
        CloseHandle(hCom);
    }
    
    void ComPort::InitComPort(void)
    {
        DCB Dcb{};
        COMMTIMEOUTS Cto{};
    
        //if ((hCom = CreateFile(TEXT("COM3:"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
        if ((hCom = CreateFile(TEXT("\\\\.\\COM3"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE)
        {
            Dcb.DCBlength = sizeof(Dcb);
            GetCommState(hCom, &Dcb);
            Dcb.BaudRate = 4800;
            Dcb.fParity = false;
            Dcb.fNull = false;
            Dcb.StopBits = ONESTOPBIT;
            Dcb.Parity = NOPARITY;
            Dcb.ByteSize = 8;
            Dcb.EvtChar = 'X';
            SetCommState(hCom, &Dcb);
    
            Cto.ReadIntervalTimeout = 0;
            Cto.ReadTotalTimeoutMultiplier = 0;
            Cto.ReadTotalTimeoutConstant = 0;
            Cto.WriteTotalTimeoutMultiplier = 0;
            Cto.WriteTotalTimeoutConstant = 0;
            SetCommTimeouts(hCom, &Cto);
    
            cout << "Port opened" << endl;
        }
        else
        {
            cout << "Couldn't open Port" << endl << "ERROR: " << GetLastError() << endl;
        }
    }
    
    int ComPort::Read() const
    {
        DWORD mask = 0;
        DWORD bytesRead = 0;
        char buf[1024] = "";
        char buf_E[1024] = "";
        int i = 0;
    
        SetCommMask(hCom, EV_RXCHAR | EV_RXFLAG | EV_RXFLAG);
        while (true)
        {
            if (WaitCommEvent(hCom, &mask, 0))
            {
                cout << "mask " << mask << endl;
                switch (mask)
                {
                case EV_RXCHAR:
                    ReadFile(hCom, &buf[i++], 1, &bytesRead, NULL);
                    cout << "Empfangen: " << buf[i - 1] << endl;
                    if (buf[i - 1] == '@') exit;         // Einlesen Ende wenn Zeichen '@' gesendet wird
                    break;
                case EV_ERR:
                    cout << "Fehler beim lesen" << endl;
                    break;
                case EV_RXFLAG:
                    cout << "Eventchar empfangen" << endl;
                    break;
                }
            }
        }
        return bytesRead;
    }
    
    int ComPort::Write() const
    {
        DWORD BytesWritten = 0;
    
        //char buf[] = "Hallo";
        char buf[] = "X";
    
        if (!WriteFile(hCom, buf, 1, &BytesWritten, NULL))
        {
            cout << "Error writing to Port" << endl;
            return -1;
        }
    
        return BytesWritten;
    }
    
    int main() {
        DWORD BytesRead = 0;
        ComPort var1;
        var1.InitComPort();
        var1.Write();           // Zeichen 'X' senden
        BytesRead = var1.Read();
        cout << "BytesRead " << BytesRead << endl;
        system("pause");
        return 0;
    }
    
    // ComPort.h
    #pragma once
    
    #ifndef _COMPORT_H_
    #define _COMPORT_H_
    
    #include "windows.h"
    #include <iostream>
    
    using namespace std;
    
    class ComPort
    {
    public:
        ComPort(void);
        ~ComPort(void);
        void InitComPort(void);
        int Read() const;
        int Read_org() const;
        int Write() const;
    
    private:
        HANDLE hCom;
    };
    
    #endif
    

    Das Einlesen des Textes funktioniert soweit.
    Wie aber kann ich das Einlesen mit "Read()" benden.
    Mein Versuch war das Einlesen benden wenn z.B. das Zeichen '@' gesendet wird: " if (buf[i - 1] == '@') exit;".
    Funktioniert leider nicht, das Einlesen wird nicht beendet.
    Juergen



  • exit; macht nicht das was du vermutlich willst. Es macht nämlich gar nix. exit ist nämlich in C++ kein Keyword. exit ist eine Standard-Library Funktion, die dein Programm beendet. Wenn du diese aufrufen wolltest, müsstest du exit(123); schreiben, bzw. statt 123 was auch immer der Exit-Code sein soll.

    Nur exit, ohne () ist kein Funktionsaufruf. Daher läuft dein Programm dann weiter. Nur was ist exit, ohne (), und warum bekommst du keinen Fehler? Der Grund ist dass du in C++ als "Anweisung" sog. "Expressions" (Ausdrücke) hinschreiben kannst -- auch wenn diese nichts tun. Und exit ist so ein Ausdruck. Er hat einen Wert (eine Referenz auf die exit Funktion), aber keinen Effekt. Macht in diesem Fall keinen Sinn, ist aber erlaubt. Wobei dein Compiler dir hier eine Warning geben sollte. Wie z.B.:

    <source>:5:5: warning: expression result unused [-Wunused-value]
        exit;
    

    Wobei vermutlich willst du gar nicht exit aufrufen, sondern dass der Programm nach der while (true) Schleife weitermacht. Wie geht das? z.B. mit goto:

    int ComPort::Read() const
    {
    ...
        while (true)
        {
    ...
                    if (buf[i - 1] == '@') goto done;         // Einlesen Ende wenn Zeichen '@' gesendet wird
    ...
        }
    done:
        return bytesRead;
    }
    

    Wobei es einen viel eleganteren Weg gibt: du kannst dort wo du die Funktion verlassen willst einfach direkt return bytesRead; hinschreiben. Also einfach

    int ComPort::Read() const
    {
    ...
        while (true)
        {
    ...
                    if (buf[i - 1] == '@') return bytesRead;    // Einlesen Ende wenn Zeichen '@' gesendet wird
    ...
        }
        // Hier brauchst du kein return, da diese Stelle sowieso nie erreicht werden kann.
    }
    


  • ps: du solltest den Returnwert von ReadFile prüfen und Fehler behandeln.


Anmelden zum Antworten