Parse a data frame in C?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • ipkiss
    New Member
    • Mar 2010
    • 4

    Parse a data frame in C?

    I am writing a program that reads the data from the serial port on Linux.
    The data are sent by another device in the following frame format:

    ---------------------------------------------------------------------
    |start | Command | Data | CRC | End |
    |0x02| 0x41 | (0-127 octets) | | 0x03|
    --------------------------------------------------------------------

    The Data field contains 127 octets as shown and octet 1,2 contains one type of data; octet 3,4 contains another data. I need to get these data

    I know how to write and read data to and from a serial port in Linux, but it is just to write and read a simple string (like "ABD")


    My issue is that I do not know how to parse the data frame formatted as above so that I can:

    - get the data in octet 1,2 in the Data field
    - get the data in octet 3,4 in the Data field
    - get the value in CRC field to check the consistency of the data

    Here the sample snip code that read and write a simple string from and to a serial port in Linux:

    Code:
        
    int writeport(int fd, char *chars) {
    	int len = strlen(chars);
    	chars[len] = 0x0d; // stick a <CR> after the command
    	chars[len+1] = 0x00; // terminate the string properly
    	int n = write(fd, chars, strlen(chars));
    	if (n < 0) {
    		fputs("write failed!\n", stderr);
    		return 0;
    	}
    	return 1;                                                                       	                                
    }
    
    int readport(int fd, char *result) {
    	int iIn = read(fd, result, 254);
    	result[iIn-1] = 0x00;
    	if (iIn < 0) {
    		if (errno == EAGAIN) {
    			printf("SERIAL EAGAIN ERROR\n");
    			return 0;
    		} else {
    			printf("SERIAL read error %d %s\n", errno, strerror(errno));
    			return 0;
    		}
    	}                    
    	return 1;
    }
    Does anyone please have some ideas?
    Thanks all.
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    Treat everything as unsigned char.

    What do you mean by octet? Is that 8-bits or 8 bytes?

    If you can populate your array you have your data.

    The CRC can't be calculated unless you use the same formula that was used to create the value in your data.

    Comment

    • ipkiss
      New Member
      • Mar 2010
      • 4

      #3
      Thanks a lot for you answer,

      "What do you mean by octet? Is that 8-bits or 8 bytes?" -> one octet means 1 byte -> 8bits

      "If you can populate your array you have your data" -> could you please elaborate on this please. I could not figure out how to get data in such a way because I either could not know how to send data in such a way.

      Regarding CRC: I got the CRC algorithm of that frame format. As long as I can get the CRC value of that frame, there is no issue.

      Again, I just do not know how to send and receive the data in such a way in C.

      Thanks a lot.

      Comment

      • donbock
        Recognized Expert Top Contributor
        • Mar 2008
        • 2427

        #4
        Start with an example. Pretend for a moment that the data field contains only four octets (two data items). Make up a couple of data items. Now what sequence of octets should be sent?

        Comment

        • weaknessforcats
          Recognized Expert Expert
          • Mar 2007
          • 9214

          #5
          |start | Command | Data | CRC | End |
          |0x02| 0x41 | (0-127 octets) | | 0x03|

          The 0x02 is the STX, or start-of-text.

          You read the stream byte-by-byte until you find an STX.


          Then you can read into your array until you reach the 0x03. The 0x03 is the ETX or end-of text.

          Your array should contain the command+data octets+CRC.

          This device does not use ITB (intermediate-text-block) to separate multiple command+data records passed as a block betweent the STX and ETX?

          Comment

          • ipkiss
            New Member
            • Mar 2010
            • 4

            #6
            Thanks all,

            I am trying you guys suggestion and let's you know the outcome as soon as possible

            Comment

            • Banfa
              Recognized Expert Expert
              • Feb 2006
              • 9067

              #7
              A couple of points

              weaknessforcats I'm mildly surprised you have never heard the term octet before. It is in very common usage in the communication industry meaning 1 unsigned 8 bit byte.

              ipkiss that looks similar to many communication protocols, from various bits of kit I have worked with over the years. Here is a couple of important questions:

              Can start byte (STX(0x02)) and end byte (ETX(0x03)) values appear in the data? Or is the data only printable characters?

              If they do appear in the data are they escaped in some way so that you know they are not actually the start and end of a message?

              Just looking for STX may not be sufficient to find the start of a message but it is hard to know with such an incomplete description of the communication protocol.

              Comment

              • weaknessforcats
                Recognized Expert Expert
                • Mar 2007
                • 9214

                #8
                Originally posted by Banfa
                weaknessforcats I'm mildly surprised you have never heard the term octet before. It is in very common usage in the communication industry meaning 1 unsigned 8 bit byte.
                When I did communications it was 1975 when it was called asynchronous communications. We use the tem octal but never octet. To us 8 bits was a byte.



                Originally posted by Banfa
                Can start byte (STX(0x02)) and end byte (ETX(0x03)) values appear in the data? Or is the data only printable characters?
                If they do appear in the data are they escaped in some way so that you know they are not actually the start and end of a message?
                The data is ASCII characters only. The STX/ITB/ETX was called an envelope. The data was inside the envelope. The com driver used the STX/OTB/EXT to fill the receive buffer with the data. The envelope characters were discarded by the driver.

                This type of envelope was use by an IBM protocol called BiSync. I haven't seen this used in many many years. Have a peek: http://telecom.tbi.net/bisync.htm

                Comment

                • ipkiss
                  New Member
                  • Mar 2010
                  • 4

                  #9
                  Hello guys,

                  I am testing the sending and receiving programs and got the issue:

                  In order to test with serial port, I used the socat (https://help.ubuntu.com/community/VirtualSerialPort ) to create a pair serial ports on Linux and test my program with these port.

                  The first time the program sends the data and the program receives data is ok. However, if I read again or even re-write the new data into the serial port, the return data is always null until I stop the virtual serial port and start it again, then the write and read data is ok, but still, only one time.

                  The sending and receiving code as I posted above, nothing changes.

                  Does anyone have any ideas?

                  Thanks a lot.

                  Comment

                  • Heming
                    New Member
                    • Oct 2010
                    • 1

                    #10
                    Hello ipkiss,

                    I have to write a program to read and write data from/to RS-232 on Ubuntu.
                    My data frame is exactly the same that ipkiss wrote:

                    start | Command | Data | CRC | End |
                    |0x02| 0x41 | (0-X bytes) | | 0x03|

                    Ipkis, could you tell me how you solved your problems?

                    If I use a canonical mode (http://www.easysw.com/~mike/serial/serial.html) I can read one line until "/n" but I would like to read until ETX (0x03).
                    Do you know how can I change this?
                    Thanks a lot

                    Comment

                    Working...