Thread: Problem with 0X04 and 0x0D

  1. #1
    Registered User
    Join Date
    Aug 2012
    Posts
    4

    Problem with 0X04 and 0x0D

    Currently I'm doing a project which send data:
    7E 45 00 FF FF FF FF 0A 00 0B 00 65 00 00 00 01 00 00 04 D2 F0 87 7E
    It is hexadecimal number and the 16th byte always increases. For example: 01 -> 02 -> 03 and so on.
    But why I cannot print out the 19th byte which is 0x04 and the 16th byte when it reaches to 0x04 and 0x0D.
    I know that 0x04 = EOT and 0x0D = CR.
    Any help on this???

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    the vagueness continues....

    Since you're not bothering to post either the code used to read the serial port, or the code used to print it, we can't help you.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Aug 2012
    Posts
    4
    Quote Originally Posted by eminempark View Post
    Currently I'm doing a project which send data:
    7E 45 00 FF FF FF FF 0A 00 0B 00 65 00 00 00 01 00 00 04 D2 F0 87 7E
    It is hexadecimal number and the 16th byte always increases. For example: 01 -> 02 -> 03 and so on.
    But why I cannot print out the 19th byte which is 0x04 and the 16th byte when it reaches to 0x04 and 0x0D.
    I know that 0x04 = EOT and 0x0D = CR.
    Any help on this???
    Hi Salem,
    I'm using serial port.
    Thank you

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by eminempark View Post
    I'm using serial port.
    Apparently, apart from demonstrating vagueness, you also don't properly read the responses you receive.

    Salem told you you can't expect help unless you provide code that is causing you trouble. You just reiterated that you are using the serial port. We already know that, since that is one of the few items of information you provided in your first post.

    Your code is what is doing the wrong things with that serial port. Without seeing a small sample of code that accurately represents what you are doing to that poor unassuming serial port, you cannot expect any useful advice on what your code is doing wrong.

    Maybe you think that, from a description of the symptoms, that we can identify the cause. People are not mind readers, so cannot do that. The problem is, for the symptoms you describe, there are many possible causes. The code will allow folks some chance of identifying the actual cause.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  5. #5
    Registered User
    Join Date
    Aug 2012
    Posts
    4
    Here it is
    Code:
        #include <sys/types.h>
            #include <sys/stat.h>
            #include <fcntl.h>
            #include <termios.h>
            #include <stdio.h>
            #include <stdlib.h>
            #include <string.h>
    
            /* baudrate settings are defined in <asm/termbits.h>, which is
            included by <termios.h> */
            #define BAUDRATE B57600            
            /* change this definition for the correct port */
            #define MODEMDEVICE "/dev/ttyUSB0"
            #define _POSIX_SOURCE 1 /* POSIX compliant source */
    
            #define FALSE 0
            #define TRUE 1
    
            volatile int STOP=FALSE; 
    
            main()
            {
              int fd,c, res;
              struct termios oldtio,newtio;
              char buf[255];
            /* 
              Open modem device for reading and writing and not as controlling tty
              because we don't want to get killed if linenoise sends CTRL-C.
            */
             fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
             if (fd <0) {perror(MODEMDEVICE); exit(-1); }
            
             tcgetattr(fd,&oldtio); /* save current serial port settings */
             bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */
            
            /* 
              BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
              CRTSCTS : output hardware flow control (only used if the cable has
                        all necessary lines. See sect. 7 of Serial-HOWTO)
              CS8     : 8n1 (8bit,no parity,1 stopbit)
              CLOCAL  : local connection, no modem contol
              CREAD   : enable receiving characters
            */
             newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
             
            /*
              IGNPAR  : ignore bytes with parity errors
              ICRNL   : map CR to NL (otherwise a CR input on the other computer
                        will not terminate input)
              otherwise make device raw (no other input processing)
            */
             newtio.c_iflag = IGNPAR | ICRNL;
             
            /*
             Raw output.
            */
             newtio.c_oflag = 0;
             
            /*
              ICANON  : enable canonical input
              disable all echo functionality, and don't send signals to calling program
            */
             newtio.c_lflag = ICANON;
             
            /* 
              initialize all control characters 
              default values can be found in /usr/include/termios.h, and are given
              in the comments, but we don't need them here
            */
             newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */ 
             newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
             newtio.c_cc[VERASE]   = 0;     /* del */
             newtio.c_cc[VKILL]    = 0;     /* @ */
             newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
             newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
             newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
             newtio.c_cc[VSWTC]    = 0;     /* '\0' */
             newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */ 
             newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
             newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
             newtio.c_cc[VEOL]     = 0;     /* '\0' */
             newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
             newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
             newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
             newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
             newtio.c_cc[VEOL2]    = 0;     /* '\0' */
            
            /* 
              now clean the modem line and activate the settings for the port
            */
             tcflush(fd, TCIFLUSH);
             tcsetattr(fd,TCSANOW,&newtio);
            
            /*
              terminal settings done, now handle input
              In this example, inputting a 'z' at the beginning of a line will 
              exit the program.
    
            */
        int x=0;
        char append[46];
        char frame[23];
        char remain[46];
        int a;
        int r=0;
        int totalres=0;
        int f =0;
            while (STOP==FALSE)
        {     /* loop until we have a terminating condition */
             /* read blocks program execution until a line terminating character is 
                input, even if more than 255 chars are input. If the number
                of characters read is smaller than the number of chars available,
                subsequent reads will return the remaining chars. res will be set
                to the actual number of characters actually read */
                
            res = read(fd,buf,255); 
        
            for(a=0; a<res; a++)
            {
                append[x++]=buf[a];
            /*    if (a==0x04)
                    printf ("04:");
                else    */
                    printf ("%X:", buf[a]);
            }
            printf ("   -- BUFFER RECEIVED %d\n", res);
            totalres+=res;
            printf ("TOTAL RECEIVED = %d\n", totalres);
            if (totalres >= 23)
            {
                for (a=0; a<totalres; a++)
                {
                    printf("%X:", append[a]);
                }
                printf (" -- APPEND\n");
                totalres = totalres-23;
                printf ("TOTAL REMAIN = %d\n", totalres);
                memcpy(&remain[0], &append[22], totalres);
                for (r=0; r<totalres; r++)
                {
                    printf ("%X:", remain[r+1]);
                }
                printf (" -- REMAIN\n");
                memcpy(frame, append, 23);
                for (f=0; f<23; f++)
                {            
                    printf ("%X:", frame[f]);
                }
                printf (" -- FRAME\n\n");
                memmove (&append[0], &append[22], totalres);
    
            }
            tcsetattr(fd,TCSANOW,&oldtio);
        }
    }

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    > append[x++]=buf[a];
    1. buf is 255 and append is 46
    2. x is NEVER reset back to 0

    So what you have here is a massive buffer overflow, merrily trashing memory until it finally bites the bullet.

    Consider....
    Code:
    $ cat foo.c
    #include <stdio.h>
    #include <string.h>
    
    #define READ_LEN    128
    #define FRAME_LEN   23
    
    int main()
    {
        unsigned char buff[READ_LEN+FRAME_LEN];
        unsigned char frame[FRAME_LEN];
        size_t used = 0;
        size_t free = sizeof(buff);
        
        // fill up part of the buffer
        // res = read(fd,buf+used,free);
        for ( size_t i = 0 ; i < 60 ; i++ ) {
            buff[i] = i;
        }
        used += 60; // += res
        free -= 60; // -= res
        
        while ( used >= FRAME_LEN ) {
            memcpy(frame,buff,FRAME_LEN);
            memmove(buff,buff+FRAME_LEN,used-FRAME_LEN);
            used -= FRAME_LEN;
            free += FRAME_LEN;
            for ( size_t i = 0 ; i < FRAME_LEN ; i++ ) {
                printf("%02x ", frame[i] );
            }
            printf("\n");
        }
        
        printf("%zd bytes used\n", used );
        printf("%zd bytes free\n", free );
        
        return 0;
    }
    $ gcc -std=c99 foo.c
    $ ./a.out 
    00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 
    17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 
    14 bytes used
    137 bytes free
    Since it is easy enough to make read() store data in the middle of a buffer (so long as you have a variable for the usable length), you can easily do away with all the append/remain handling.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    0x04 is EOT. My guess is that the recipient is set up to recognize this byte and believe it means the transmission is terminated.

  8. #8
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    945
    Quote Originally Posted by eminempark View Post
    Code:
            /*
              IGNPAR  : ignore bytes with parity errors
              ICRNL   : map CR to NL (otherwise a CR input on the other computer
                        will not terminate input)
              otherwise make device raw (no other input processing)
            */
             newtio.c_iflag = IGNPAR | ICRNL;
             
            /*
             Raw output.
            */
             newtio.c_oflag = 0;
             
            /*
              ICANON  : enable canonical input
              disable all echo functionality, and don't send signals to calling program
            */
             newtio.c_lflag = ICANON;
             
            /* 
              initialize all control characters 
              default values can be found in /usr/include/termios.h, and are given
              in the comments, but we don't need them here
            */
             newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */ 
             newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
             newtio.c_cc[VERASE]   = 0;     /* del */
             newtio.c_cc[VKILL]    = 0;     /* @ */
             newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
             newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
             newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
             newtio.c_cc[VSWTC]    = 0;     /* '\0' */
             newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */ 
             newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
             newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
             newtio.c_cc[VEOL]     = 0;     /* '\0' */
             newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
             newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
             newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
             newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
             newtio.c_cc[VEOL2]    = 0;     /* '\0' */
    I'm going to assume that the code you posted is the receiver, since you didn't say either way.

    Take a closer look at the code snippet I quoted above. I see a few problems.

    First, you should be calling tcgetattr() to get a termios structure that you then modify in place (you can copy the termios structure to save the termios settings for later). By "modify" I mean using Boolean operations to set or clear each flag individually, like this:
    Code:
        options.c_cflag     |= (CLOCAL | CREAD);
        options.c_lflag     &= ~(ICANON | ECHO | ECHOE | ISIG);
    Second, you're setting c_lflag to ICANON and setting VEOF to 4, which enables canonical input processing and causes read() to ignore EOT (0x04).

    Third, you setting ICRNL in c_iflag which converts CR (0x0d) to NL (0x0a) on input.

    Read this page (I've skimmed it but it looks like a good reference): Serial Programming Guide for POSIX Operating Systems
    Read the Rationale section: tcgetattr

    The biggest problem is that it looks like you just copied the source from Program Examples without changing the settings to make it work for your needs.

    I've probably spent way too much time on this thread already.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sleep() function problem or logic problem?
    By FernandoBasso in forum C Programming
    Replies: 7
    Last Post: 11-16-2011, 05:50 PM
  2. strcmp problem, whats the problem, i cant figure it out!
    By AvaGodess in forum C Programming
    Replies: 14
    Last Post: 10-18-2008, 06:45 PM
  3. Replies: 4
    Last Post: 10-16-2008, 07:30 PM
  4. sturct/pointer problem, and fscanf problem
    By hiphop4reel in forum C Programming
    Replies: 6
    Last Post: 07-28-2008, 09:40 AM
  5. syntax linked list problem & struct problem
    By beely in forum C Programming
    Replies: 5
    Last Post: 11-11-2002, 09:14 AM

Tags for this Thread