Wetterstation



  • Hallo erstmal,
    So wir haben als Projekt den Auftrag bekommen eine Wetterstation zu fertigen!
    Als Microcontroller nutzen wir das Lemps12.
    Nun da wir noch Anfänger in Sachen C++ sind sind wir ein bisschen auf Hilfe angewiesen!
    Meine erste Frage:
    Wie empfängt man Daten per Com-Schnittstelle auf dem PC?(Quellcode?)



  • Hey, cooles Projekt.

    Wie empfängt man Daten per Com-Schnittstelle auf dem PC?

    Schau mal in die Dos und Win32 Konsolen-FAQ

    (Quellcode?)

    Nanana, wer wird denn...



  • Ja cool schon aber auch schwierig für uns!
    Wir haben jetzt einen Quellcode das schreiben funktioniert schon!
    Aber beim Lesen stürzt das Programm ab!
    Hier mal der Quellcode!

    // -----------------------------------------------------------------------------------
    // (c) 2003 www.winapi.net
    //
    // Serial.cpp
    //
    // CPP-Datei für eine einfache, aber leistungsfähige 
    // Kommunikation über die Serielle Schnittstelle
    // -----------------------------------------------------------------------------------
    
    #include <windows.h>
    #include "Serial.h" // Headerdefinitionen
    #include <iostream.h>
    
    CSerial::CSerial() : hComm(INVALID_HANDLE_VALUE)
    {
    }
    
    CSerial::~CSerial()
    {
       Close ();
    }
    
    BOOL CSerial::ModeSet (int nBaud, int nBits, int nStopp, int nParity) 
    // Ändern von Baudrate (nBaud), Bits (nBits), Parität (nParity)
    {
       if (INVALID_HANDLE_VALUE == hComm) // COM-Port überhaupt geöffnet?
           return (FALSE);
    
       DCB dcb; // Struktur vom Typ DCB erzeugen
    
       ZeroMemory (&dcb, sizeof(dcb)); // ..und schön löschen (wichtig!)
    // Die bestehenden Parameter holen. Bei Fehler ist hier Schluss!
       if (!GetCommState (hComm, &dcb)) 
       {
          Close ();
          MessageBox (NULL, "Fehler beim Ändern der COM-Port Parameter\nGetCommState()", 
                      NULL, NULL);
          return (FALSE);
       }
    
       // neue Parameter in die Struktur kopieren (Baud: z.B. 9600)
       dcb.BaudRate = nBaud; 
       // neue Parameter in die Struktur kopieren (Bits: z.B. 7 oder 8)
       dcb.ByteSize = (BYTE)nBits; 
       // neue Parameter in die Struktur kopieren (Parität:(siehe MSDN))
       dcb.Parity   = (BYTE)nParity; 
       // Anzahl Stoppbits (siehe MSDN)
       dcb.StopBits = (BYTE)nStopp; 
    
       // neue Parameter setzen. Bei Fehler ist hier Schluss!
       if (!SetCommState (hComm, &dcb)) 
       {
          Close ();
          MessageBox (NULL, "Fehler beim Ändern der COM-Port Parameter\nSetCommState()", 
                      NULL, NULL);
          return (FALSE);
       }
    
       return (TRUE); // fertig
    }
    
    // Öffnen von / mit Portnummer (nPort), Baudrate (nBaud), Bits (nBits), Stoppbits (nStopp), Parität (nParity)
    
    BOOL CSerial::Open (int nPort, int nBaud, int nBits, int nStopp, int nParity) 
    {
       if (INVALID_HANDLE_VALUE != hComm)  // COM-Port überhaupt geöffnet?
           return (TRUE);
    
       char szPort[15]; 
        // Aus einer "1" in nPort schreiben wir so "COM1" in szPort z.B..
       wsprintf (szPort, "\\\\.\\COM%d", nPort);
    
       hComm = CreateFile (szPort, // COM-Port öffnen
                           GENERIC_READ | GENERIC_WRITE, // wir wollen lesen und schreiben
                           0,
                           0,
                           OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL); // nicht OVERLAPPED, wir holen uns den Port exclusiv
    
       if (hComm == INVALID_HANDLE_VALUE) // hat es geklappt? Bei Fehler ist hier Schluss!
       {
          MessageBox (NULL, "Fehler beim Öffnen des COM-Ports!\nCreateFile()", NULL, NULL);
          return (FALSE);
       }
       // Alte Timeouts merken. Bei Fehler ist hier Schluss!
       if (!GetCommTimeouts(hComm, &timeouts_alt)) 
       {
          Close ();
          MessageBox (NULL, "Fehler beim Öffnen des COM-Ports!\nGetCommTimeouts()", 
                      NULL, NULL);
          return (FALSE);
       }
    
       // Eine Struktur vom Typ COMMTIMEOUTS erzeugen und neue Timeouts setzen
       COMMTIMEOUTS timeouts; 
       timeouts.ReadIntervalTimeout         = 200;
       timeouts.ReadTotalTimeoutMultiplier  = 200;
       timeouts.ReadTotalTimeoutConstant    = 200;
       timeouts.WriteTotalTimeoutMultiplier = 200;
       timeouts.WriteTotalTimeoutConstant   = 200;
    
       // Neue Timeouts setzen. Bei Fehler ist hier Schluss!
       if (!SetCommTimeouts(hComm, &timeouts)) 
       {
          Close ();
          MessageBox (NULL, "Fehler beim Öffnen des COM-Ports!\nSetCommTimeouts()", 
                      NULL, NULL);
          return (FALSE);
       }
    
       DCB dcb; // Struktur vom Typ DCB erzeugen
    
       ZeroMemory (&dcb, sizeof(dcb)); // ..und schön löschen (wichtig!)
       // Die bestehenden Parameter holen. Bei Fehler ist hier Schluss!
       if (!GetCommState (hComm, &dcb)) 
       {
          Close ();
          MessageBox (NULL, "Fehler beim Öffnen des COM-Ports!\nGetCommState()", 
                      NULL, NULL);
          return (FALSE);
       }
    
       dcb_alt = dcb; // alte Parameter sichern
       dcb.DCBlength         = sizeof(DCB);
       dcb.fBinary           = TRUE; // muss immer "TRUE" sein!
       dcb.fParity           = TRUE;
       dcb.fOutxCtsFlow      = FALSE;
       dcb.fOutxDsrFlow      = FALSE;
       dcb.fDtrControl       = DTR_CONTROL_ENABLE;
       dcb.fDsrSensitivity   = FALSE;
       dcb.fTXContinueOnXoff = TRUE;
       dcb.fOutX             = FALSE;
       dcb.fInX              = FALSE;
       dcb.fErrorChar        = FALSE;
       dcb.fNull             = FALSE;
       dcb.fRtsControl       = RTS_CONTROL_ENABLE;
       dcb.fAbortOnError     = FALSE;
       dcb.wReserved         = 0; // muss immer "0" sein!
    
       // neue Parameter in die Struktur kopieren (Baud: z.B. 9600)
       dcb.BaudRate = nBaud; 
       // neue Parameter in die Struktur kopieren (Bits: z.B. 7 oder 8)
       dcb.ByteSize = (BYTE)nBits; 
       // neue Parameter in die Struktur kopieren (Parität:(siehe MSDN))
       dcb.Parity   = (BYTE)nParity; 
       // Anzahl Stoppbits (siehe MSDN)
       dcb.StopBits = (BYTE)nStopp; 
       dcb.fParity = (dcb.Parity != NOPARITY);
    
       // neue Parameter setzen. Bei Fehler ist hier Schluss!
       if (!SetCommState (hComm, &dcb)) 
       {
          Close ();
          MessageBox (NULL, "Fehler beim setzen der COM-Port Parameter\nSetCommState()", 
                      NULL, NULL);
          return (FALSE);
       }
    
       return(TRUE);
    }
    
    BOOL CSerial::Close (void)
    {
       if (INVALID_HANDLE_VALUE == hComm) // COM-Port überhaupt geöffnet?
           return(TRUE);
    
       if (!SetCommTimeouts(hComm, &timeouts_alt))
       {
          MessageBox (NULL, "Fehler beim Schließen des COM-Ports\nSetCommTimeouts()", 
                      NULL, NULL);
          return (FALSE);
       }
       // alte Parameter zurückschreiben. Bei Fehler ist hier Schluss!
       if (!SetCommState (hComm, &dcb_alt)) 
       {
          MessageBox (NULL, "Fehler beim Schließen des COM-Ports\nSetCommState()", 
                      NULL, NULL);
          return (FALSE);
       }
       CloseHandle (hComm); // Port schließen
       hComm = INVALID_HANDLE_VALUE; // das Handle zurücksetzen
    
       return (TRUE);
    }
    
    BOOL CSerial::WriteCommByte (unsigned char ucByte) // Das zu übertragene Byte (ucByte)
    {
       if (INVALID_HANDLE_VALUE == hComm) // COM-Port überhaupt geöffnet?
           return(FALSE);
    
       // ein Zeichen direkt übertragen. Bei Fehler ist hier Schluss!
       if (!TransmitCommChar(hComm, ucByte)) 
       {
          MessageBox (NULL, "Fehler beim Schreiben auf COM-Port!\nTransmitCommChar()", 
                      NULL, NULL);
       }
    
       return (TRUE);
    }
    
    int CSerial::SendData (const char *buffer, int iBytesToWrite) 
    // Buffer (*buffer), mit den zu sendenen Zeichen und deren Anzahl (iBytesToWrite)
    {
       if(INVALID_HANDLE_VALUE == hComm) // COM-Port überhaupt geöffnet?
           return(0);
    
       DWORD dwBytesWritten = 0;
       // die angegebene Anzahl der Bytes schreiben
       WriteFile(hComm, buffer, iBytesToWrite, &dwBytesWritten, NULL); 
    
       return ((int) dwBytesWritten); // die Anzahl der geschriebenen Bytes zurückgeben
    }
    
    int CSerial::ReadData (char *buffer) // Buffer (*buffer), der die Zeichen bekommt
    {
       if (INVALID_HANDLE_VALUE == hComm) // COM-Port überhaupt geöffnet?
           return(0);
    
       DWORD dwRead = 0;
       char chRead;
       int i = 0;
    
       while (ReadFile(hComm, &chRead, 1, &dwRead, NULL)) // wurde ein Zeichen gelesen?
       {
    
           if (dwRead != 1) // ..wenn nicht, dann ist hier Schluß
    	   {
    
    		   MessageBox (NULL, "Lesefehler vom COM-Port!\nReadFile()", 
                      NULL, NULL);
    
               break;
    	   }
    
           buffer[i++] = chRead; // wann ja, dann das Zeichen in den Buffer schreiben
       }
    
       return (i); // die Anzahl der gelesenen Bytes zurückgeben
    }
    
    int main()
    {
    
    	// Öffnen von / mit Portnummer (nPort), Baudrate (nBaud), Bits (nBits), Stoppbits (nStopp), Parität (nParity)
    
    	CSerial test;
    
    	test.Open(4,19200,8,2,0);
    	test.SendData("c", 1);
    	Sleep(100);
    	test.SendData("w", 1);
    	test.ReadData("3");
    	test.Close();
    return 0;
    }
    

    und die header

    // -----------------------------------------------------------------------------------
    // (c) 2003 www.winapi.net
    //
    // Serial.h
    //
    // Headerdatei für eine einfache, aber leistungsfähige 
    // Kommunikation über die Serielle Schnittstelle
    // -----------------------------------------------------------------------------------
    
    #ifndef __SERIAL_H__
    #define __SERIAL_H__
    
    class CSerial
    {
    
    public:
       CSerial(); // Konstruktor
       ~CSerial(); // Destructor
    
       BOOL Open    (int, int, int, int, int); // Öffnen 
       BOOL Close   (void); // Schließen
       BOOL ModeSet (int, int, int, int); // Änderung
    
       int ReadData (char*); // Lesen
       int SendData (const char*, int); // Schreiben
       BOOL WriteCommByte (unsigned char); // Schreiben eines Zeichens
    
    private:
       HANDLE hComm; // Handle für den Zugriff
       DCB dcb_alt; // Um die alten Parameter zu merken
       COMMTIMEOUTS timeouts_alt; // Um die alten Parameter zu merken
    };
    
    #endif
    

    Kompilierbar ist es allerdings kommt im Debugger der Fehler:
    Unbehandelte Ausnahme in comschnitt.exe: 0x0000005: Access Violation
    Der Debugger springt auf die Zeile mit dem buffer[i++].
    Ich vermute es liegt an der zeile mit
    test.ReadData("3") da mir nicht ganz klar ist was dort als string rein muss



  • Du hast vermutlich recht.
    Wenn du ein Stringliteral übergibst (das ist das, was im Quelltext zwischen den "" steht), dann ist dieser String als const anzusehen und darf nicht beschrieben werden. Du kannst z.B. ein char Array erstellen.
    z.b.

    char buf[256];
      test.ReadData(buf);
    

    Außerdem ist nicht klar, wie viele Zeichen maximal in den Buffer geschrieben werden können. Du kannst also nicht sicher sein, ob kein Pufferüberlauf stattfindet. Deshalb wirst du noch einen Parameter übergeben müssen, der die maximale Größe des Puffers angibt.



  • Ja Überlauf wirds wohl sein!
    Allerdings können wir nicht wissen wie groß die Datei auf der anderen Seite ist!
    Sie wird nämlich fortlaufen größer!
    Dein String Array ergibt die selbst gefertigte Fehlermeldung:
    Leserfehler ReadFile()



  • ⚠ Für spezielle Programmierprobleme wende dich bitte an das entsprechende Fachforum.


Anmelden zum Antworten