Reading Binary

Discussion in 'Open Source' started by Doddy, Dec 16, 2004.

Thread Status:
Not open for further replies.
  1. Doddy

    Doddy New Member

    Joined:
    Dec 10, 2004
    Messages:
    30
    Likes Received:
    0
    Trophy Points:
    0
    I am doing a hurry to complete a project in Linux, to read binary data from a meter or device through a serial port and write the data into a binary or text file. I really need the solutions fast.

    How am I going to receive the BINARY data correctly from the serial port?

    I encountered problem when I tried to read the data using the way I read ASCII data, but it don't work as binary data will make the ASCII value, out of range in the ASCII table and return me with a question mark, '?' instead.

    I have no idea of how to change the code below to read in binary data or straight away write into a file. I know some people suggested to open the port as using a file handler or something similar and write the data read from the port straight into a file.
    But as I am very new to Comms and Linux programming, how am I going to do that.
    It is best if you can provide a workable solution.

    Below is my subroutine of the code to read in ASCII data:

    int read_reg()
    {
    int bytes_received, bytes_required;
    char file_name[18];

    bytes_received= 0;
    bytes_required = 255; // For example i'm reading 255 bytes

    sprintf(file_name, "Test.dat");
    fa = fopen (file_name, "a");

    while (bytes_received < bytes_requried)
    {
    fcntl(ttyfd, F_SETFL, FNDELAY);
    rxchar = rxchar & 0xff;
    recv[bytes_received] = rxchar;
    bytes_received++;
    fprintf(fa, "%0.2X", rxchar);
    }

    fclose(fa);
    }
     
  2. #/bin/sh

    #/bin/sh New Member

    Joined:
    Apr 20, 2004
    Messages:
    213
    Likes Received:
    0
    Trophy Points:
    0
    Location:
    42.65 N 73.76 W
    I don't see where you actually do the read() to get the data!
    Please show all your code.
     
  3. OP
    OP
    Doddy

    Doddy New Member

    Joined:
    Dec 10, 2004
    Messages:
    30
    Likes Received:
    0
    Trophy Points:
    0
    Sorry about that. Below is the code that I used to read data:

    int m;
    int rxchar = -11;

    if((m = read(ttyfd,&rxchar,1)) != -1)
    {
    if(rxchar != -11)
    {
    rxchar = rxchar & 0xff; // the data will be 0xFFFFxx if I don't & with 0xFF
    // after I & with 0xFF, rxchar will become 0xXX
    recv[bytes_received] = rxchar;
    bytes_received++;
    fprintf(fa," 0x%0.2X", rxchar);
    }

    else
    printf("Failed to read from device\n");
    }
     
  4. #/bin/sh

    #/bin/sh New Member

    Joined:
    Apr 20, 2004
    Messages:
    213
    Likes Received:
    0
    Trophy Points:
    0
    Location:
    42.65 N 73.76 W
    Are you correctly setting the port to 8N1 (8bit,no parity,1 stopbit)? E.g.

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <termios.h>
    #include <stdio.h>

    /* baudrate settings are defined in <asm/termbits.h>, which is
    included by <termios.h> */
    #define BAUDRATE B38400
    /* change this definition for the correct port */
    #define MODEMDEVICE "/dev/ttyS1"
    #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.
    */
    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);
    buf[res]=0; /* set end of string, so we can printf */
    printf(":%s:%d\n", buf, res);
    if (buf[0]=='z') STOP=TRUE;
    }
    /* restore the old port settings */
    tcsetattr(fd,TCSANOW,&oldtio);
    }
     
  5. OP
    OP
    Doddy

    Doddy New Member

    Joined:
    Dec 10, 2004
    Messages:
    30
    Likes Received:
    0
    Trophy Points:
    0
    If i use a variable to accept binary data, then if I want to save the data received, into binary format too, then what data type should I use to write the data?

    eg. int, hex or char?

    My hardware sent the binary data which is already in the format for processing by another program in the PC.
    So I need to preserve the original binary format.

    what I hope is to be able to straightaway write the binary data received to a file, instead of using don't know what variable to temporary store the data, and later don't know save in what format.
     
  6. OP
    OP
    Doddy

    Doddy New Member

    Joined:
    Dec 10, 2004
    Messages:
    30
    Likes Received:
    0
    Trophy Points:
    0
    How do I store the received data in binary and in the same format as what I received from the serial port?
     
  7. #/bin/sh

    #/bin/sh New Member

    Joined:
    Apr 20, 2004
    Messages:
    213
    Likes Received:
    0
    Trophy Points:
    0
    Location:
    42.65 N 73.76 W
Thread Status:
Not open for further replies.

Share This Page