Seriellen Datenempfang in TXT Datei abspeichern



  • Hallo,

    ich ahbe zum Datenlogging folgenden Code erstellt:

    [code]
    //----------------------------------------------------------------------
    // Titel     : Seriell Logger
    //----------------------------------------------------------------------
    // Sprache   : C
    // Datum     : 27.10.14
    // IDE       : wxDev
    //----------------------------------------------------------------------
    #include <stdio.h>
    #include <windows.h>
    #include "com.h"
    
    int main(int argc, char* argv[])
    {   
        //Serielle Schnittstelle öffnen
        HANDLE hComm= CreateFile("Com4",
               GENERIC_READ | GENERIC_WRITE,
               0,
               NULL,   
               OPEN_EXISTING,
               FILE_ATTRIBUTE_NORMAL,
               NULL);           
        ini_com( 9600 , &hComm);  
    
        //Datei zum reinschreiben erstellen
        FILE *fdatei= fopen("inputdata.txt","w+");
        if(fdatei == NULL) 
        {
              MessageBox(NULL,"Fehler beim erstellen der Datei.","Fehler!", MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_OK); 
              exit(1);
        }     
    
        char eingabe=0, com_inputc;   
        while(1)
        {
            if(kbhit()) //wenn eine Taste gedrückt wurde...
            {
                eingabe=getch();
                switch(eingabe)
                {
                    case 27:     //wenn ESC gedrückt wurde...
                        CloseHandle(hComm);
                        fclose(fdatei);
                        exit(0);
                    default:
                        com_putc(eingabe, &hComm);  //sende das eingegebene Zeichen
                        break;                      
                }
                eingabe=0;  
            }
    
            if( com_getc(&com_inputc, hComm) == TRUE)   //Serielle Schnittstelle nach neuen Zeichen abfragen
            {
                printf("%c", com_inputc);           //das Empfangene Zeichen in der Konsole ausgeben
                fprintf( fdatei, "%c", com_inputc); //das Empfangene Zeichen in die Datei schreiben
            }
        }
    
        return 0;  
    
    }
    

    Nun wird aber kontinuierlich in die TXT Datei geschrieben.
    Ich möchte aber, dass nachdem die erste Zeile empfangen wurde (endet mit Zeilenumbruch), das selbe passiert als wenn ich die ESC-Taste drücke, so dass immer nur ein Datensatz (die zuletzt empfangene Zeile) in der Datei geschrieben wird.

    Ich habe auch schon versucht mit

    remove("inputdata.txt");
    

    Die Datei danach zu löschen, jedoch geht das zu schnell.

    Habt ihr eine Idee?

    LG Dennis



  • Mein Trollalarm ringt, aber ich antworte mal trotzdem ...

    Was genau willst du? Was macht dein Programm? Wäre es möglich, dass du den Beitrag editierst, um dem ganzen C-Codetags zu geben? Und was hält dich davon ab, com_inputc auf '\r' oder '\n' zu prüfen und es wie hier beschrieben zu machen?



  • Oder suchst du nach http://www.cplusplus.com/reference/cstdio/rewind/ ?

    Und schau dir da dann auch gleich mal fputc und putchar an.



  • Anbei noch die code.h

    [code]
    #ifndef com_h_INCLUDED
    #define com_h_INCLUDED
    
    #include <conio.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    
    DWORD dwWritten;
    
    DCB dcb;
    COMMTIMEOUTS commtimeouts;
    
    DWORD commerr;
    COMSTAT comstat;
    DWORD bytes_read;
    
    void com_putc(char c, HANDLE *hComm)
    {
         if( !WriteFile(*hComm, &c, sizeof(c), &dwWritten, 0) ) printf("serial port write failed\n");
    }
    ////
    char com_getc(char *com_inputc, HANDLE hComm)
    {
         ClearCommError(hComm, &commerr, &comstat);
         if(comstat.cbInQue != 0 && ReadFile(hComm, com_inputc, 1, &bytes_read, NULL) != 0) return TRUE;
         else return FALSE;
    }
    ////
    void Fehlerausgabe(char fehlercode)
    {
        printf("Fehlercode: %i", fehlercode);      
        MessageBox(NULL,"Fehler","Error!", MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_OK); 
        exit(0);
    }
    //----------------------------------------------------------------------
    void ini_com(float baudrate, HANDLE *pComm)
    {
       // Port geöffnet?
       if(pComm == INVALID_HANDLE_VALUE)
       { 
            MessageBox(NULL,"COM Port schon geöffnet.\nSchließen Sie alle Programme die auf den COM Port zugreifen.","Fehler!",
             MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_OK); 
            exit(0);
       }
       // IO-Buffer setzen
       if(SetupComm(*pComm, 2048, 2048) == FALSE) 
       { 
            MessageBox(NULL,"COM Port konnte nicht erstellt werden.\nPrüfen Sie ob der COM Port im Gerätemanager vorhanden ist.",
             "Fehler!", MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_OK); 
            exit(0);
       }
       // COM-Port einstellen
       if(GetCommState(*pComm, &dcb) == FALSE)
       { 
            MessageBox(NULL,"COM Port konnte nicht Eingestellt werden","Fehler!", MB_ICONEXCLAMATION | MB_SETFOREGROUND | MB_OK); 
            exit(0);
        }
    
       dcb.BaudRate =  baudrate;                // current baud rate
       dcb.fParity = FALSE;                     // enable parity checking
       dcb.fOutxCtsFlow = FALSE;                // Bestimmt, ob der Ausgabehandshake, der das CTS (Clear To Send)-Signal verwendet, ein- oder ausgeschaltet ist.
       dcb.fOutxDsrFlow = FALSE;                // Bestimmt, ob der Ausgabehandshake, der das DSR (Data Set Ready)-Signal verwendet, ein- oder ausgeschaltet ist.
       dcb.fDtrControl = DTR_CONTROL_ENABLE;    // Bestimmt, ob das DTR (Data Terminal Ready)-Signal ein, aus oder auf Handshake (hs) bzw. umschaltbar (tg) ist.
       dcb.fDsrSensitivity = FALSE;             // DSR sensitivity
       dcb.fTXContinueOnXoff = FALSE;           // XOFF continues Tx
       dcb.fOutX = FALSE;                       // XON/XOFF out flow control
       dcb.fInX = FALSE;                        // XON/XOFF in flow control
       dcb.fErrorChar = FALSE;                  // enable error replacement
       dcb.fNull = FALSE;                       // enable null stripping
       dcb.fRtsControl = RTS_CONTROL_ENABLE;    // RTS flow control
       dcb.fAbortOnError = FALSE;               // abort reads/writes on error
       // dcb.fDummy2 = fDummy2;                // reserved
       // dcb.wReserved = wReserved;            // not currently used
       dcb.XonLim = 0;                          // transmit XON threshold
       dcb.XoffLim = 0;                         // transmit XOFF threshold
       dcb.ByteSize = 8;                        // number of bits/byte, 4-8
       dcb.Parity = NOPARITY;                   // 0-4=no,odd,even,mark,space
       dcb.StopBits = ONESTOPBIT;               // value 0,1,2 = 1, 1.5, 2 stop bits
       dcb.XonChar = 0;                         // Tx and Rx XON character
       dcb.XoffChar = 0;                        // Tx and Rx XOFF character
       dcb.ErrorChar = 0;                       // error replacement character
       dcb.EofChar = 0;                         // end of input character
       dcb.EvtChar = 0;                         // received event character 
       dcb.fBinary = TRUE;                      // binary mode, no EOF check
    
       if(SetCommState(*pComm, &dcb) == FALSE) Fehlerausgabe(1);
    
       memset(&commtimeouts, 0, sizeof(COMMTIMEOUTS));                                  // Timout setzen
       if(SetCommTimeouts(*pComm, &commtimeouts) == FALSE) Fehlerausgabe(2);   
       dcb.fBinary = TRUE;                                                              // binary mode, no EOF check   
       PurgeComm(pComm, PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR); // IO-Buffer leeren
    }
    #endif
    


  • Sry, habe den Beitrag editiert.
    Also das Programm wartet jetzt auf Daten die auf der seriellen Schnittstelle von einem Mikrocontroller gesendet werden und speichert diese kontinuierlich in einer TXT Datei ab. Gibt es die TXT Datei noch nicht, legt er diese an. Das Programm kann mit der ESC - Taste beendet werden.

    Für mich ist aber wichtig, dass immer nur ein Datenpaket, welches mit einen Zeilenumbruch endet in die TXT Datei geschrieben wird. Also eigentlich muss das Programm einfach noch dahingehend optimiert werden, dass wenn es auf der seriellen Schnittstelle einen Zeilenumbruch erkennt das selbe macht, als wenn man die ESC Taste drückt also:

    case 27:     //wenn ESC gedrückt wurde...
                        CloseHandle(hComm);
                        fclose(fdatei);
                        exit(0);
    

    mein fehlendes Wissen hält mich davon ab 😉

    Kann jemand diese zusätzliche IF-Abfrage in den Code einpflegen?

    LG



  • if (com_inputc == '\n')
    { 
      .....
    
    }
    

Anmelden zum Antworten