Serielle Schnittstelle mit 3 Drähten, ReadFile()



  • Hallo,
    also ich hab mir ne Verbindung zwischen 2 PCs mit 3 Drähten über die Rs232-Schnittstelle gebaut.

    Ich hab mir dann auch n VB programm heruntergeladen. Mit dem Programm kann ich dann "chatten".

    Nun hab ich versucht das gleiche in C zu machen. Wenn ich auf dem PC1 des VB-prog hab und auf PC2 mein eigenes, dann kann ich von PC2 auf PC1 auch chararrays senden, aber nicht empfangen.
    D.h. mit dem c prog kann ich nur senden, ich will aber auch empfangen.

    hierm mein code:

    #include <stdio.h>
    #include <windows.h>
    #include <process.h>
    
    #define MAX 256
    
    unsigned __stdcall SecondThreadFunc(void* pArguments);
    
    HANDLE hCom;
    
    int main()
    {
      // CREATE THREAD
      HANDLE hThread;
      unsigned threadID;
    
      COMMTIMEOUTS CommTimeouts;
    
      DWORD wieviel;//dwEvtMask;
      DCB dcb;
      DWORD dw = GetLastError();
      char buf[MAX];
      int boll = 0;
      int rc = 1;
    
      hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );
    
      hCom = CreateFile("COM2",GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);  //anstatt NULL : FILE_FLAG_OVERLAPPED
      if(hCom == INVALID_HANDLE_VALUE)
      {
            printf("COM Port ist besetzt");
            getchar();
            return 1;
      }
      else
            printf("COM Port OK\n");
    
      boll = SetupComm(hCom, MAX, MAX); // set buffer sizes
      if(boll!=0)
           printf("1 alles ok\n");
      else
           printf("1 nö Fehler\n");
    
      getchar();
    
        ///////////////////////////////////////////////////////
    
    // Initialize the DCBlength member.
    dcb.DCBlength = sizeof (DCB);
    
    // Get the default port setting information.
    GetCommState (hCom, &dcb);
    
    // Change the DCB structure settings.
    dcb.BaudRate = 19200;              // Current baud
    //dcb.fBinary = TRUE;               // Binary mode; no EOF check
    dcb.fParity = TRUE;               // Enable parity checking
    dcb.fOutxCtsFlow = FALSE;         // No CTS output flow control
    dcb.fOutxDsrFlow = FALSE;         // No DSR output flow control
    //dcb.fDtrControl = DTR_CONTROL_ENABLE;
                                          // DTR flow control type
    //dcb.fDsrSensitivity = FALSE;      // DSR sensitivity
    //dcb.fTXContinueOnXoff = TRUE;     // XOFF continues Tx
    dcb.fOutX = FALSE;                // No XON/XOFF out flow control
    dcb.fInX = FALSE;                 // No XON/XOFF in flow control
    dcb.fErrorChar = FALSE;           // Disable error replacement
    dcb.fNull = FALSE;                // Disable null stripping
    //dcb.fRtsControl = RTS_CONTROL_ENABLE;
                                          // RTS flow control
    dcb.fAbortOnError = FALSE;        // Do not abort reads/writes on
                                          // error
    dcb.ByteSize = 8;                 // Number of bits/byte, 4-8
    dcb.Parity = NOPARITY;            // 0-4=no,odd,even,mark,space
    dcb.StopBits = ONESTOPBIT;        // 0,1,2 = 1, 1.5, 2
    
    // Configure the port according to the specifications of the DCB
    // structure.
    if (!SetCommState (hCom, &dcb))
    {
      // Could not configure the serial port.
      printf("%d\n",GetLastError());
    
      return FALSE;
    }
    else
    printf("Jo alles klar\n");
    
    //////////////////////////////////////////////////////////////////////////
    
    // Retrieve the timeout parameters for all read and write operations
    // on the port. 
    
    GetCommTimeouts (hCom, &CommTimeouts);
    
    // Change the COMMTIMEOUTS structure settings.
    CommTimeouts.ReadIntervalTimeout = MAXDWORD;
    CommTimeouts.ReadTotalTimeoutMultiplier = 0;
    CommTimeouts.ReadTotalTimeoutConstant = 0;
    CommTimeouts.WriteTotalTimeoutMultiplier = 10;  
    CommTimeouts.WriteTotalTimeoutConstant = 1000;    
    
    // Set the timeout parameters for all read and write operations
    // on the port. 
    if (!SetCommTimeouts (hCom, &CommTimeouts))
    {
      // Could not set the timeout parameters.
    printf("error:%d\n",GetLastError ());
      return FALSE;
    }
    else
       printf("timeouts ok\n");
    
    memset(buf,0,MAX);
    
       while(rc)
       {
            memset(buf,0,MAX);
    
            gets(buf);
            if(buf[0]=='?')
               exit(1);
    
            rc = WriteFile(hCom,&buf,strlen(buf),&wieviel,NULL);
            printf("rc:%i|buf:%s",rc,buf);
        }
    
       printf("Fehler:%i|%d\n",rc,GetLastError());
    
        getchar();
        CloseHandle(hCom);
        CloseHandle(hThread);
        return 0;
    
    }
    
    unsigned __stdcall SecondThreadFunc( void* pArguments )
    {
    
      char buf[MAX];
      DWORD wieviel;
      int rc=1;
    
      while(rc)
      {
          memset(buf,0,MAX);
    
         rc = ReadFile(hCom,&buf,MAX/*strlen(buf)*/,&wieviel,NULL);
              printf("____rc:%i|-- %s____",rc,buf);
    
      }
    
      printf("Fehler:%i\n",rc);
    
      _endthreadex(0);
      return 0;
    
    }
    

    wurde teilweise einfach aus der msdn kopiert.

    Sieht hier jemand n Fehler?

    Gruß
    Scrat1



  • Der zweite Thread läuft sofort nach dem _beginthreadex los. Zu dem Zeitpunkt hast du hCom aber noch gar nicht initialisiert.

    Außerdem solltest du im zweiten Thread irgendeine Abbruchbedingung in die while-Schleife einfügen und am Ende nicht _endthreadex aufrufen, sondern einfach mit return zurückkehren.

    Allerdings: Poste doch bitte nur die relevanten Code-Teile (welche das sind, kannst du z.B. mit dem Debugger ermitteln). Dann bekommst du viel eher Hilfe.

    p.s.: Deine Fehlerbehandlung sieht etwas seltsam aus. Wenn du einen Fehler feststellst, solltest du das Programm kontrolliert beenden lassen oder den Fehler korrigieren. Du gibst aber nur eine Fehlermeldung aus und machst mit den ungültigen Variablen weiter.



  • Danke für die Hinweise.

    Hab den Threadfehlerbehoben, dannach lief alles.

    Hier der komplette Code(funktioniert wunderbar):

    #include <stdio.h>
    #include <windows.h>
    #include <process.h>
    
    #define MAX 256
    
    unsigned __stdcall SecondThreadFunc(void* pArguments);
    HANDLE hCom;
    
    int main()
    {
      // CREATE THREAD
      HANDLE hThread;
      unsigned threadID;
    
      COMMTIMEOUTS CommTimeouts;
      DWORD wieviel;//dwEvtMask;
      DCB dcb;
      char buf[MAX];
      int boll = 0;
      int rc = 1;
    
    // Initialisiere serielle Schnittstelle
      hCom = CreateFile( "COM2",
                       GENERIC_READ|GENERIC_WRITE,
                       0,
                       0,
                       OPEN_EXISTING,
                       FILE_FLAG_OVERLAPPED,
                       0);
    
      if(hCom == INVALID_HANDLE_VALUE)
      {
        printf("COM Port ist besetzt");
        getchar();
        return 1;
      }
      else
            printf("COM Port     O.k.\n");
    
    // konfiguriere serielle Schnittstelle
      boll = SetupComm(hCom, MAX, MAX); // set buffer sizes
      if(boll!=0)
        printf("buffer sizes O.k.\n");
      else
      {
        printf("buffer sizes Fehler:|%d\n",GetLastError());
        getchar();
        return FALSE;
      }
    
    // weitere Einstellungen
      dcb.DCBlength = sizeof (DCB);
    
      GetCommState (hCom, &dcb);
    
      dcb.BaudRate = 19200;                //CBR_9600;  //CBR_4800;   //und mehr;  einfach mal 9600 oder 19200
      dcb.Parity = NOPARITY;               //EVENPARITY;//ODDPARITY;
      dcb.StopBits = ONESTOPBIT;          //ONESTOPBIT;//TWOSTOPBITS;
    
      if (!SetCommState (hCom, &dcb))
      {
        printf("Eintragung der Einstellungen Fehlgeschlagen:|%d\n",GetLastError());
        getchar();
        return FALSE;
      }
      else
        printf("Eintragung   O.k.\n");
    
    // Timeouts der Schnittstelle konfigurieren
      GetCommTimeouts (hCom, &CommTimeouts);
    
      CommTimeouts.ReadIntervalTimeout = MAXDWORD;
      CommTimeouts.ReadTotalTimeoutMultiplier = 0;  //von msdn 0
      CommTimeouts.ReadTotalTimeoutConstant = 0; //von msdn 0     // von mir 100
      CommTimeouts.WriteTotalTimeoutMultiplier = 10;  //von msdn 10
      CommTimeouts.WriteTotalTimeoutConstant = 1000;    //von msdn 1000
    
      if (!SetCommTimeouts (hCom, &CommTimeouts))
      {
        printf("Eintragung der Timeouts fehlgeschlagen:|%d\n",GetLastError ());
        getchar();
        return FALSE;
      }
      else
        printf("Timeouts     O.k.\n");
    
    // Starten des Threads
      hThread = (HANDLE)_beginthreadex( NULL,
                                      0,
                                      &SecondThreadFunc,
                                      NULL,
                                      0,
                                      &threadID );
    
      if(hThread ==  -1 || hThread==0)
      {
        printf("Starten des Threads fehlgeschlagen:|%d\n",GetLastError());
        getchar();
        return FALSE;
      }
      else
         printf("Thread Start O.k.\n");
    
      while(rc)
      {
        memset(buf,0,MAX);
        gets(buf);
    
        if(buf[0]=='?')
          exit(1);
    
        rc = WriteFile(hCom,&buf,strlen(buf),&wieviel,NULL);
      }
    
      printf("Fehler beim Schreiben:|%d\n",rc,GetLastError());
    
      getchar();
      CloseHandle(hCom);
      CloseHandle(hThread);
      _endthreadex(0);
      return 0;
    }
    
    unsigned __stdcall SecondThreadFunc( void* pArguments )
    {
    
      char buf[MAX];
      DWORD wieviel;
      int rc=1;
    
      while(rc)
      {
        memset(buf,0,MAX);
        rc = ReadFile(hCom,&buf,MAX,&wieviel,NULL);
    
        if(wieviel>0)
          printf("%s_\n",buf);
      }
    
      printf("Fehler beim Empfangen:|%d\n",GetLastError());
    
      //_endthreadex(0);
      return 0;
    }
    

    Sieht hoffentlich besser aus 😉

    Gruß
    Scrat1


Anmelden zum Antworten