Hilfe beim kommunikation mit COM Port



  • Hab das jetzt mal so probiert aber er gibt immer den selben Wert aus. das kann ja auch nicht richtig sein, weil sich ja der Wert des Schibers verändert.



  • Mir fällt gerade auf, dass du für c garkeinen Speicher allozierst 😮
    Ansonsten sieht das eigentlich ganz OK aus.
    Was genau ist denn das für ein Messschieber? Gibt's da 'nen Datenblatt zu?

    Mfg, North.



  • Was genau meinst du mir allozieren? (auch wenn doof klingt)
    Es ist ein Digitalschieber und hat Werte mit 3 Nachkomm stellen. Ein Datenblatt gibt es glaub ich nicht mehr.



  • char *c; reserviert nur den Speicher für einen Pointer auf char.
    Wenn du den mit Leben füllen willst, dann musst du dem noch entsprechend der Anzahl der Element Speicher zuweisen.
    Also,
    1. dynamisch:

    char *c;
    c = (char*)malloc(4*sizeof(char));
    

    oder

    c = (char*)calloc(4,sizeof(char));
    

    oder

    c = (char*)LocalAlloc(LMEM_ZEROINIT,4*sizeof(char));
    

    2. statisch

    char c[4];
    

    Bei 1. am Schluß nicht das free(c) bzw. LocalFree(c) vergessen.
    Komisch, dass dein Programm nicht abgeschmiert ist.

    Mfg, North.



  • Also es hat sich schon mal was getan aber er gibt immer noch eine Zahl aus und zwar immer die selbe. Trotz Veränderung am Schieber. Kann es sein das gar nicht der COM Port angesprochen wird?



  • OK, das kriegen wir schon raus.
    1. Überprüf doch mal mit dem Hyperterminal o.ä. was an der seriellen Schnittstelle ankommt.
    2. Check mal die Rückgabewerte der Methoden die du aufrufst.
    3. Steht da auf deinem Schieber nicht irgend ein Name oder Nummer drauf nach der man mal googeln könnte?

    Mfg, North.



  • Hi

    Also, ich würde auch erstmal anfangen, alle rückgabewerte zu überprüfen, und über GetLastError rauskriegen, ob alles geklappt hat.

    Dann mußt du erstmal wissen, welche baudrate der Meßschieber braucht, 9600 ist zwar anzunehmen, aber man weiß nie.

    Dein Pointer auf char sollte genausogroß sein, wie iMaxCount.

    Mfg Reinhold Fischer



  • Etwas andere Wortwahl aber im Grunde was ich meinte 🙂



  • Merci. Hab ich gemacht! Aber jetzt sagt er Fehler beim Setzen der Com Port Parameter.

    Hab hier mal den aktuellen Code:

    #include <iostream>
    #include <windows.h>
    
    class CSerial
    {
    
    public:
    	CSerial();
    	~CSerial();
    
    	BOOL Open (int nComPortNr, int nBaud, int nBits, int nParity, int nStopp);
    	BOOL Close (void);
    	BOOL ModeSet (int nBaud, int nBits, int nParity, int nStopp);
    	BOOL SetTimeout (int iTotalReadTimeout);
    	BOOL IsOpen (void);
    
    	int ReadData (char *buffer, int iMaxCount);
    	int SendData (const char *buffer, int iBytesToWrite);
    	BOOL WriteCommByte (unsigned char ucByte);
    
    private:
    	HANDLE hComm;
    	DCB dcb_alt;
    	COMMTIMEOUTS timeouts_alt;
    };
    
    CSerial::CSerial()
    {
    	hComm = INVALID_HANDLE_VALUE;
    }
    
    CSerial::~CSerial()
    {
    	Close ();
    }
    
    BOOL CSerial::IsOpen()
    {
       if (INVALID_HANDLE_VALUE != hComm)
           return (TRUE);
    	else
    		return (FALSE);
    }
    
    BOOL CSerial::ModeSet (int nBaud, int nBits, int nParity, int nStopp)
    {
       if (INVALID_HANDLE_VALUE == hComm)
    	{
    		SetLastError(ERROR_INVALID_HANDLE);
          return (FALSE);
    	}
    
       DCB dcb;
    
       ZeroMemory (&dcb, sizeof(dcb));
    	dcb.DCBlength = sizeof(DCB);
    
       if (!GetCommState (hComm, &dcb))
    	{
    		//close();
    		MessageBox (NULL, "Fehler beim Ändern der COM-Port Parameter\nGetCommState()",
                      NULL, NULL);
    		return (FALSE);
    	}
    
       dcb.BaudRate = nBaud;
       dcb.ByteSize = (BYTE)nBits;
       dcb.Parity   = (BYTE)nParity;
    	dcb.StopBits = (BYTE)nStopp;
    
       if (!SetCommState (hComm, &dcb))
      {
          Close ();
          MessageBox (NULL, "Fehler beim Ändern der COM-Port Parameter\nSetCommState()",
                      NULL, NULL);
          return (FALSE);
       }
    
    	return (TRUE);
    }
    
    BOOL CSerial::Open (int nComPortNr, int nBaud, int nBits, int nParity, int nStopp)
    {
       if (INVALID_HANDLE_VALUE != hComm)
    	{
          return (TRUE);
    	}
    
       char szPort[16];
    
       wsprintf (szPort, "\\\\.\\COM%d", nComPortNr);
    
       hComm = CreateFile (szPort,
    						  GENERIC_READ | GENERIC_WRITE,
                        0,
                        0,
                        OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL);
    
       if (hComm == INVALID_HANDLE_VALUE)
       {
          MessageBox (NULL, "Fehler beim Öffnen des COM-Ports!\nCreateFile()", NULL, NULL);
    
          return (FALSE);
       }
    
       if (!GetCommTimeouts(hComm, &timeouts_alt))
       {
    		DWORD dwError = GetLastError();
    		Close ();
    		SetLastError(dwError);
    
          		MessageBox (NULL, "Fehler beim Öffnen des COM-Ports!\nGetCommTimeouts()",
                      NULL, NULL);
          	return (FALSE);
    
       }
    
       COMMTIMEOUTS timeouts;
       timeouts.ReadIntervalTimeout = MAXDWORD ;
       timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ;
       timeouts.ReadTotalTimeoutConstant = 3000; // Timeout ist 3000ms
       timeouts.WriteTotalTimeoutMultiplier = 1000;
       timeouts.WriteTotalTimeoutConstant = 1000;
    
       if (!SetCommTimeouts(hComm, &timeouts))
       {
    		DWORD dwError = GetLastError();
    		Close ();
    		SetLastError(dwError);
    		MessageBox (NULL, "Fehler beim Öffnen des COM-Ports!\nSetCommTimeouts()",
                      NULL, NULL);
    
          return (FALSE);
       }
    
       DCB dcb;
       ZeroMemory (&dcb, sizeof(dcb));
    	dcb.DCBlength = sizeof(DCB);
    
       if (!GetCommState (hComm, &dcb))
       {
    		DWORD dwError = GetLastError();
    		Close ();
    		SetLastError(dwError);
    		MessageBox (NULL, "Fehler beim Öffnen des COM-Ports!\nGetCommState()",
                      NULL, NULL);
    
          return (FALSE);
       }
    
    	dcb_alt = 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!
    
    	dcb.BaudRate = nBaud;
    	dcb.ByteSize = (BYTE)nBits;
    	dcb.Parity   = (BYTE)nParity;
    	dcb.StopBits = (BYTE)nStopp;
    
       dcb.fParity = (dcb.Parity != NOPARITY);
    
       if (!SetCommState(hComm, &dcb))
       {
    		DWORD dwError = GetLastError();
    		Close ();
    		SetLastError(dwError);
    		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::SetTimeout (int iTotalReadTimeout)
    {
       if (INVALID_HANDLE_VALUE == hComm)
          return (TRUE);
    
       COMMTIMEOUTS timeouts;
       timeouts.ReadIntervalTimeout = MAXDWORD ;
       timeouts.ReadTotalTimeoutMultiplier = MAXDWORD ;
       timeouts.ReadTotalTimeoutConstant = (DWORD) iTotalReadTimeout;
       timeouts.WriteTotalTimeoutMultiplier = 1000;
       timeouts.WriteTotalTimeoutConstant = 1000;
    
       if (!SetCommTimeouts(hComm, &timeouts))
    
          return (FALSE);
    
       return(TRUE);
    }
    
    BOOL CSerial::WriteCommByte (unsigned char ucByte)
    {
       if (INVALID_HANDLE_VALUE == hComm)
    	{
    
          	return (FALSE);
    	}
    
       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)
    {
       if (INVALID_HANDLE_VALUE == hComm)
    	{
    
          return (0);
    	}
    
       DWORD dwBytesWritten = 0;
       WriteFile(hComm, buffer, iBytesToWrite, &dwBytesWritten, NULL);
    
       return ((int) dwBytesWritten);
    }
    
    int CSerial::ReadData (char *buffer, int iMaxCount)
    {
       if (INVALID_HANDLE_VALUE == hComm)
    	{
    		SetLastError(ERROR_INVALID_HANDLE);
          return (0);
    	}
    
       DWORD dwRead = 0;
       char chRead;
       int i = 0;
    
       while (ReadFile(hComm, &chRead, 1, &dwRead, NULL))
       {
           if (dwRead != 1)
               break;
    
           buffer[i++] = chRead;
    
    		 if (i == iMaxCount)
    			 break;
    	}
    
    	return (i);
    }
    

    Aber die Parameter müssten eigentlich stimmen. Hab da bei Systemsteuerung Ssytem.. die COM eigenschaften übernommen oder müssen da andere rein??



  • Füg doch mal anstatt:

    SetLastError(dwError);
    MessageBox (NULL, "Fehler beim setzen der COM-Port Parameter\nSetCommState()",
                      NULL, NULL);
    

    folgendes ein:

    LPVOID	error_text;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
                 |FORMAT_MESSAGE_FROM_SYSTEM
                 |FORMAT_MESSAGE_FROM_HMODULE
                 |FORMAT_MESSAGE_IGNORE_INSERTS
                 ,NULL,dwError,0,(LPTSTR) &error_text,0,NULL);
    MessageBox(NULL,(LPCSTR)error_text,NULL,NULL);
    LocalFree(error_text);
    

    und sag was er ausgibt.

    Mfg, North.



  • Hab ich gemacht!

    Jetzt zeigt er das Fehlerfenster aber es steht nix drin also alles grau?
    Was sagt mir das jetzt? Na ich hoffe euch sagt es was denn ich steh ziehmlich auf'm Schlauch.



  • Bin ich jetzt doof 😕
    Der sollte dir dann eigentlich die Fehlermeldung von SetCommState() ausgeben...
    Was hat denn dwError für 'nen Wert?



  • Sorry für doppelpost:

    Probier mal FormatMessage ohne |FORMAT_MESSAGE_FROM_HMODULE



  • Er gibt aus:

    Fehler falscher Parameter! 😕

    Das hat ich doch schonmal...



  • Kalle77 schrieb:

    Das hat ich doch schonmal...

    Wann? Bisher wußten wir nur wo der Fehler auftrat, jetzt wissen wir was es für ein Fehler ist.
    Also ich mache bei mir folgende Einstellungen:

    ZeroMemory (&dcb, sizeof(dcb));
    dcb.DCBlength=sizeof(sDcb);
    dcb.BaudRate		= 9600;
    dcb.fParity		= FALSE;
    dcb.fBinary		= TRUE;
    dcb.Parity		= NOPARITY;
    dcb.StopBits		= ONESTOPBIT;
    dcb.fOutxCtsFlow	 	= FALSE;
    dcb.fOutxDsrFlow 		= FALSE;
    dcb.fDtrControl		= DTR_CONTROL_ENABLE;
    dcb.fRtsControl		= RTS_CONTROL_ENABLE;
    dcb.fDsrSensitivity	= FALSE;
    dcb.fAbortOnError		= FALSE;
    dcb.ByteSize		= 8;
    

    Den Rest lasse ich unverändert(auch kein GetCommState).
    Damit klappts.

    MfG, North.



  • Die Fehlermeldung hatte ich heut gegen 11:00 schon mal irgendwie!

    Also nach der Änderung bringt er jetzt 3 Fehlermeldungen
    1. Fehler beim schließen des COM Ports SetCommState()
    2. Fehler beim ändern des COM Ports SetCommState()
    3. Fehler beim schließen des COM Ports SetCommState()



  • Wenn ich das richtig sehe, gibt's jetz kein Prblem mehr beim Öffnen des Ports.
    Hast du immernoch ModeSet in deiner main? Wenn ja, schmeiß raus.



  • Sorry habe das Problem immer noch! ModeSet hab ich rausgehauen und jetzt kommt der Fehler beim schließen. Nur warum ist die Frage? irgendwelche Anregungen. Ich find der Code scheint ganz okay zu sein!



  • Das Problem beim Öffnen waren falsche Settings in der DCB Struktur. Ich schätze mal das ist beim Schließen dann auch das Problem. Da soll ja anscheinend der Ausgangszustand wieder hergestellt werden(was ich persönlich unnötig finde). Speicherst du denn überhaupt noch die alten Settings mit GetCommState in dcb_alt? Wenn nicht schmeiß entweder das SetCommState aus der Close Methode raus oder hol dir beim Öffnen doch wieder die alten Settings.

    MfG, North.



  • Also die Fehlermeldungen sind auf jedenfall schon mal weg. Habe die Setcommstate aus Close rausgeschmissen1 Aber er bringt trotzdem nur wirre Werte. Scheinbar kann er keine Verbindung zum Schieber aufnehmen oder er empfängt nichts bzw was falsches! Oder was meinst du?


Anmelden zum Antworten