0

I am making a simple C program to get data serially from a serial device. The data is in hex format. Before writing the code I checked it in cutecom and I was receiving 25 54 00 1e which is the correct and exact value. But when I write the code then I receive this BFE50A14 which is wrong data. I dont know where I am making a mistake, please help. Thanks.!

CODE:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <math.h>

#define portname "/dev/ttyUSB0"

int set_interface_attribs (int fd, int speed, int parity)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                // error_message ("error %d from tcgetattr", errno);
                printf("error opening the device");
                return -1;
        }

        cfsetospeed (&tty, speed);
        cfsetispeed (&tty, speed);

        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
        // disable IGNBRK for mismatched speed tests; otherwise receive break
        // as \000 chars
        tty.c_iflag &= ~IGNBRK;         // disable break processing
        tty.c_lflag = 0;                // no signaling chars, no echo,
                                    // no canonical processing
        tty.c_oflag = 0;                // no remapping, no delays
        tty.c_cc[VMIN]  = 0;            // read doesn't block
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                    // enable reading
        tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
        tty.c_cflag |= parity;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
            // error_message ("error %d from tcsetattr", errno);
            printf("error opening the device");
            return -1;
        }
        return 0;
}

int set_blocking (int fd, int should_block)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
            //error_message ("error %d from tggetattr", errno);
            printf("error opening the device");
            return;
        }

        tty.c_cc[VMIN]  = should_block ? 1 : 0;
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
          //  error_message ("error %d setting term attributes", errno);
            printf("error opening the device");
}


int main()
{


    int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
    if (fd < 0)
    {

            printf("error opening the device");

    }
/*CHANGES*/
if(!set_interface_attribs(fd, B9600, 0))
        {
            printf("error set interface");
        }
        else
           printf("correct");
        if(!set_blocking(fd, 0))
        {
            printf("error set blocking");
        }
        else
            printf("done");
*/
    set_interface_attribs (fd, B9600, 0);


    set_blocking (fd, 0);                // set no blocking

    usleep ((7 + 25) * 100);             

    int receivebuffer [10];

    read (fd, receivebuffer, sizeof receivebuffer);
/***CHANGES***//
    printf("value of buffer is %2X %2X %2X %2X \n\n", receivebuffer[0],receivebuffer[1],receivebuffer[2],receivebuffer[3]);



return 0;
}

I am receiving the data in receivebuffer and I am printing it using printf and using %X to print it in hex format. The output I am getting is BFE50A14 but the correct output is 25 54 00 1e . Please help, Thanks.!

Undefined Behavior
  • 2,128
  • 4
  • 24
  • 34
user46573544
  • 137
  • 3
  • 4
  • 13
  • the original values for the serial port should be saved (in a global variable for instance) so they can be restored just before the program exits – user3629249 Mar 25 '15 at 06:26
  • both set_interface-atribs() and set_blocking() should return a status. Main() should check that status from each call to determine if it is to continue, rather than assuming the attribute modifications were all successful – user3629249 Mar 25 '15 at 06:34
  • the array receivebuffer[] should be cleared, via int receivebuffer[10] = {'0'}; however, characters are being read, not integers, so it should be char receivebuffer[10] = {'\0'}; – user3629249 Mar 25 '15 at 06:38
  • the returned value from read() needs to be checked to see in any (and how many) characters were read. initializing receivebuffer[] ahead of time to all '\0' means a string NUL termination char will be properly set – user3629249 Mar 25 '15 at 06:40
  • the correct output contains data from 4 bytes . separated by a space, however the printf statement is not formatting that . the printf statement is formatting a hex string, no spaces, etc. suggest a format string that contains: ".... %2X %2X %2X %2X\n\n", receiveBuffer[0], receiveBuffer[1], receiveBuffer[2], receiveBuffer[3] ); – user3629249 Mar 25 '15 at 06:42
  • @user3629249 How can I check for that status in main – user46573544 Mar 25 '15 at 06:45
  • what is the use of 2 in %2X.? – user46573544 Mar 25 '15 at 06:47
  • have each of the sub functions return an int value where that int value indicates success or failure, I.E. re -1 if failure, return 0 if successful Then in main if( !set_interface-attribs(...)) { // then successful if( !set_blocking(...) ) { // then successful .... note the '...' mean include the attributes or current processing – user3629249 Mar 25 '15 at 06:48
  • the 2 in %2X means to output 2 hex characters. (the 2 is needed so'zero suppression' does not drop a leading 0 and will always use 2 print characters) – user3629249 Mar 25 '15 at 06:50
  • how is the user expected to input a '\0' char from the terminal (the 00 in the expected output)? – user3629249 Mar 25 '15 at 06:54
  • while checking the status in main, what should i include in (..) like if(!set_interface-attribs(??). – user46573544 Mar 25 '15 at 06:55
  • Ok I have checked the status in main. – user46573544 Mar 25 '15 at 06:57
  • 1
    suggest reading the man page for printf, suggest learning about function return values, suggest reading the man page for read – user3629249 Mar 25 '15 at 06:57
  • I am getting the output as 71 B7 00 00 but it should be 25 54. any idea.? please help, thanks – user46573544 Mar 25 '15 at 06:58
  • hey I got the value 25 54 but the problem is it should be constant but it is changing when ever I am executing again and again – user46573544 Mar 25 '15 at 07:00
  • amongst other things, it looks like the number of stop bits and the baud rate between your program and the terminal do not match. exactly what is the user entering at the terminal? – user3629249 Mar 25 '15 at 07:02
  • yeah that was baudrate problem, I have changed it to 9600 but still the problem is same ie values are changing again and again. BTW i have updated the code – user46573544 Mar 25 '15 at 07:06
  • '25' hex is the '%' symbol. how are you entering that at the terminal? '54' is a 'T' symbol. how are you entering that at the terminal? '00' is a NUL symbol, how are you entering that at the terminal? '1E' is a record separator symbol. How are you entering that at the terminal? – user3629249 Mar 25 '15 at 07:09
  • the function: set_blocking() is still returning 'void' rather than 'int', has no return value statement just before the final closing brace and the one return statement in the middle of the code has no value. – user3629249 Mar 25 '15 at 07:11
  • I am not entering anything at the terminal. I am getting these values on the terminal – user46573544 Mar 25 '15 at 07:12
  • then where are the value coming from? – user3629249 Mar 25 '15 at 07:13
  • sorry about the void, i forgot to change it here. The values are coming from serial device. – user46573544 Mar 25 '15 at 07:13
  • how do you know the incoming values are 1) always aligned with the time when the code reads the values and that the contents of the values are always the same 4 bytes? Note: I need to sign off (after midnight here) I'll look for this question tomorrow, but might not be able to find it. – user3629249 Mar 25 '15 at 07:15
  • I know that because I have programmed the microcontroller in the device. This I have done in windows and i was receiving the exact values in docklight. In ubuntu, I have checked this in cutecom software(which is serial terminal) and was giving me 25 54. but this program is giving me some wrong data – user46573544 Mar 25 '15 at 07:18

1 Answers1

0

here is what we have covered so far in comments:

Note: this only vaguely resembles the code most recently posted

Note: do not use tabs in your code. because
      different editors have the tab stops and/or tab width
      set differently

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <math.h>

#define portname "/dev/ttyUSB0"

static struct termios oldtty;

int set_interface_attribs (int fd, int speed, int parity)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &oldtty) != 0)
        {
                // error_message ("error %d from tcgetattr", errno);
                printf("error opening the device");
                return -1;
        }

        memcpy( tty, oldtty, sizeof struct termion );

        cfsetospeed (&tty, speed);
        cfsetispeed (&tty, speed);

        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
        // disable IGNBRK for mismatched speed tests; otherwise receive break
        // as \000 chars
        tty.c_iflag &= ~IGNBRK;         // disable break processing
        tty.c_lflag = 0;                // no signaling chars, no echo,
                                    // no canonical processing
        tty.c_oflag = 0;                // no remapping, no delays
        tty.c_cc[VMIN]  = 0;            // read doesn't block
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                    // enable reading
        tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
        tty.c_cflag |= parity;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
            // error_message ("error %d from tcsetattr", errno);
            printf("error opening the device");
            return -1;
        }
        return 0;
} // end function: set_interface_attribs


int set_blocking (int fd, int should_block)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
            //error_message ("error %d from tggetattr", errno);
            printf("error opening the device");
            return -1;
        }

        tty.c_cc[VMIN]  = should_block ? 1 : 0;
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
          //  error_message ("error %d setting term attributes", errno);
            printf("error opening the device");
    return 0;
} // end function: set_blocking


int main()
{
    int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
    if (fd < 0)
    {
        printf("error opening the device");
    }


    /*CHANGES*/
    if(!set_interface_attribs(fd, B9600, 0))
    {
        printf("error set interface");
    }

    else
       printf("correct");

    if(!set_blocking(fd, 0))
    {
        printf("error set blocking");
    }

    else
        printf("done");

    // what is this stray end of comment?  
    // suggest enabling all the compiler warings
    // and fixing the warnings 
    // */
    if( set_interface_attribs (fd, B9600, 0) )
    { // then set_interface_attribs failed
        return -1;
    }

    // implied else set_interface_attribs successful

    if( set_blocking (fd, 0) )                // set no blocking
    { // then set_blocking failed
        return -1;   // might need to also restore oldtty attributes
    }

    // implied else, set_blocking successful

    usleep ((7 + 25) * 100);             

    char receivebuffer [20];

    if( 4 > read (fd, receivebuffer, sizeof receivebuffer) )
    { // then read failed
        return -1;
    }

    // implied else, read successful

    printf("value of buffer is %2X %2X %2X %2X \n\n", 
        receivebuffer[0],
        receivebuffer[1],
        receivebuffer[2],
        receivebuffer[3]);

    // cleanup
    tcsetattr (fd, TCSANOW, &oldtty);
    return 0;
} // end function: main
user3629249
  • 16,402
  • 1
  • 16
  • 17