Serieller Datenstrom: Anfang und Ende eines Paketes erkennen



  • Hallo miteinander,
    ich habe von der seriellen Schnittstelle eines Videomischers Daten ausgelesen und zunächst in einer File gespeichert. Ich muss diese nun irgendwie verarbeiten. Dabei weiß ich wie ein Paket anfängt (mit fffff und dann einer Zahl), was einer "Adresse" entspricht.

    Leider habe ich auch nach langem googlen nichts passendes gefunden, wie man einen seriellen Stream in einzelne Pakete "zerhakt" bzw. erkennt wo ein Paket anfängt und wo es aufhört.

    Ich dachte mir zunächst: Nun gut, ich habe ja ein char-Array mit allen gesendeten Daten. Dann schaue ich mir jeden Char an, wandle ihn in einen INT um und schaue ob dieser Wert dann über einem Schwellwert liegt. Leider klappt das nicht wirklich, habt ihr eine Idee?

    Ich hab schon mit strtol und atoi rumgespielt, doch da kommen fast nur Werte wie 0,1,2,3,4,5 raus. Wenn ich mir den Char fffff9e anschaue, entspricht das allerdings einem weitaus höherem Wert dezimal betrachtet.

    ISt das der falsche Ansatz sowas zu machen?

    Vielen Dank schonmal für eure Hilfe!

    Gruß,
    marham

    //
    //  main.cpp
    //  CplusPlusSpielerein
    //
    //  Created by XX on 7/19/12.
    //  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
    //
    
    #include <iostream> 
    #include <cstring> 
    #include <string.h>
    #include <limits.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sstream>
    #include <iomanip>
    #include <locale>
    
    using namespace std;
    
    int main(int argc, char** argv) 
    { 
    
        FILE * pFile;
        long lSize;
        char * buffer;
        size_t result;
    
        pFile = fopen ( "/Users/user1234/input3-38400MixTSL" , "rb" );
        if (pFile==NULL) {fputs ("File error",stderr); exit (1);}
    
        // obtain file size:
        fseek (pFile , 0 , SEEK_END);
        lSize = ftell (pFile);
        rewind (pFile);
    
        // allocate memory to contain the whole file:
        buffer = (char*) malloc (sizeof(char)*lSize);
        if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
    
        // copy the file into the buffer:
        result = fread (buffer,1,lSize,pFile);
        if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
    
        /* the whole file is now loaded in the memory buffer. */
    
        for(int i = 0; i < lSize ; i++)
        {
        //printf("%x\n", buffer[i]);
           // int intFromChar = atoi(buffer[i]);
    
            int sum;
            long sum2;
            sum2 = strtol(&buffer[i],NULL,8);
    		sum = atoi( &buffer[i] );
    
            unsigned long x;
            x = strtoul(&buffer[i], 0, 16);
    
            cout<<sum<<endl;
    
               printf("%x\n", buffer[i]);
    
        cout << endl;
    
        }
    
        // terminate
        fclose (pFile);
        free (buffer);
        return 0;
    

  • Mod

    marham schrieb:

    Ich dachte mir zunächst: Nun gut, ich habe ja ein char-Array mit allen gesendeten Daten. Dann schaue ich mir jeden Char an, wandle ihn in einen INT um und schaue ob dieser Wert dann über einem Schwellwert liegt. Leider klappt das nicht wirklich, habt ihr eine Idee?

    Das klingt eigentlich richtig.

    Ich hab schon mit strtol und atoi rumgespielt, doch da kommen fast nur Werte wie 0,1,2,3,4,5 raus.

    Nicht nur, dass das ein C/C++-Gemisch ist, das ist auch von der Idee her falsch. Im Stream steht ja nicht wirklich 'F','F',F','F', sondern 255, 255. Und damit meine ich nicht '2','5','5','2','5','5' sondern wirklich die Zahlenwerte. Mit atoi&Co. würdest du versuchen, eine Darstellung eines Zahlenwertes zu interpretieren. Dabei hast du die Zahlenwerte doch schon und kannst direkt mit diesen arbeiten.

    //
    //  main.cpp
    //  CplusPlusSpielerein
    //
    //  Created by XX on 7/19/12.
    //  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
    //
    
    #include <iostream> 
    #include <cstring> 
    #include <string.h>
    #include <limits.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sstream>
    #include <iomanip>
    #include <locale>
    
    using namespace std;
    
    int main(int argc, char** argv) 
    { 
        
        
        FILE * pFile;
        long lSize;
        char * buffer;
        size_t result;
        
        pFile = fopen ( "/Users/user1234/input3-38400MixTSL" , "rb" );
        if (pFile==NULL) {fputs ("File error",stderr); exit (1);}
        
        // obtain file size:
        fseek (pFile , 0 , SEEK_END);
        lSize = ftell (pFile);
        rewind (pFile);
        
        // allocate memory to contain the whole file:
        buffer = (char*) malloc (sizeof(char)*lSize);
        if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
        
        // copy the file into the buffer:
        result = fread (buffer,1,lSize,pFile);
        if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
        
        /* the whole file is now loaded in the memory buffer. */
       
     
        for(int i = 0; i < lSize ; i++)
        {
        //printf("%x\n", buffer[i]);
           // int intFromChar = atoi(buffer[i]);
            
            int sum;
            long sum2;
            sum2 = strtol(&buffer[i],NULL,8);
    		sum = atoi( &buffer[i] );
            
            unsigned long x;
            x = strtoul(&buffer[i], 0, 16);
           
            
            cout<<sum<<endl;
            
               printf("%x\n", buffer[i]);
            
    		 
        cout << endl;
        
        }
        
        // terminate
        fclose (pFile);
        free (buffer);
        return 0;
    

    Grauenhaft. Mische niemals C und C++! Du versuchst anscheinend C zu machen und hast dir aus Internettutorials versehentlich ein paar Fetzen C++ reinkopiert. Liege ich damit richtig? Besorg dir ein vernünftiges Lehrbuch, versuche nicht, dir aus dem Internet die Grundlagen zu zwei so ähnlichnamigen Sprachen zu besorgen. Das geht schief!



  • Also erstmal beginnt der Falsche Ansatz schon damit, dass du bis auf das eine cout ausschließlich C benutzt hast. Wenn ich allein schon fputs(/*...*/, stderr); lese, wird mir Angst. Guck dir std::cerr an. Malloc verwendet in C++-Zeiten keiner mehr. Guck dir new an. fopen & co. verwendet in C++ auch keiner mehr. Guck dir std::(i)fstream an. Du brauchst auch kein printf um dir Daten hexadezimal ausgeben zu lassen: cout << hex << zahl;

    Auf das eigentliche Programm hab ich noch gar nicht so richtig geschaut, aber mir schein als versuchtest du mit atoi Binärdaten umwandeln zu wollen. atoi ist nur dafür da, C-Strings, die eine Zahl in Textform beinhaltet umzuwandeln. Aber schreib dein Programm erstmal nach C++ um, oder lass dich nach C verschieben.

    EDIT: BBCode macht mich wahnsinnig!



  • Da hast du Recht 😉 Ich hab mal mein C++ Buch ausgegraben und versuch es damit.

    Vielleicht kannst du mir da helfen:

    int i2;
            i2 = static_cast<int>(buffer[i]);
    
               printf("%x\n", buffer[i]);
    

    Der printf-Befehl gibt: ffffff9e aus, in der Variable i2 steht aber -98
    Im nächsten Durchlauf der for-Schleife gibt der printbefehl: 30 aus und i2 48



  • marham schrieb:

    Der printf-Befehl gibt: ffffff9e aus, in der Variable i2 steht aber -98
    Im nächsten Durchlauf der for-Schleife gibt der printbefehl: 30 aus und i2 48

    Beides korrekt. Hex 30 ist dezimal 48. Und für die -98 schau mal hier.



  • Vielen Dank nochmal, habe das jetzt so lösen können:

    int i2;
            i2 = static_cast<int>(buffer[i]);
            if (i2 < -96)
            {
                for (int i3 =1; i3 <= 16; i3++)
                {
                    cout << buffer[i+1+i3];
                }
    
                cout << hex<<  int(buffer[i+20]) << " " ;
                cout <<hex <<  int(buffer[i+21]) << endl;
            }
    

    das gibt mir nun genau folgendes aus:

    BLACK          0 0
     BLACK          0 0
    INPUT01         20 0
    INPUT02         0 0
    INPUT03         0 0
    INPUT04         0 0
    INPUT05         0 0
    INPUT06         0 0
    INPUT07         0 0
    INPUT08         0 0
    

    So wollte ich das haben. Nun muss ich nur noch statt einer Textfile, den wirklich seriellen Stream auslesen. Da habe ich schonmal ein Programm geschrieben, wobei mir die Buffer-Thematik noch etwas befremdlich ist. Aber das ist dann später vielleicht Thema für einen anderen Thread?!


Anmelden zum Antworten