LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   serial port not filling buffer entirely (http://www.linuxquestions.org/questions/programming-9/serial-port-not-filling-buffer-entirely-660568/)

windell 08-05-2008 05:42 AM

serial port not filling buffer entirely
 
Hi, I'm writing a program that fetches 38 byte samples via the serial port. After each fetch I print out the amount of bytes read and then print out the hex representation of the array of characters. I throw away 4 bytes from the beginning of each sample therefore I only want to read 34 bytes each pass through the program.

During a run, most of the new byte counts are 34 however some of them are 33, 7 etc. In addition, when I print the hex representation not all of the characters print. For example for a 34 byte character array, only 13 bytes printed out.

I have the serial port setup for non-canonical reading however...i followed a tutorial so I do not know the if I am setting up a serial port properly for my application.

I have a feeling that it has to do with the serial port forcing itself to return before 34 bytes are read. And the printf is taking too long so the program stops it and moves on.

I would like to make sure that I am reading sold 34 bytes each pass and would like to print them to the screen for debugging.

Any pointers would be greatly appreciated!

I have pasted my configuration code and read code below. init_port is the function called to do the configuration.

Code:

int main()
{
char port_name[] = "/dev/ttyUSB0";        //set port name here.
int fd;

//-------------open ports---------------------------------
fd = open(port_name, O_RDWR | O_NOCTTY | O_NDELAY);

if (fd == -1){
        perror("unable to open /dev/ttyUSB0\n");
        return 1;
}
else
{
        printf("Connected to %s\n",port_name);
        fcntl(fd,F_SETFL,0);
}
//----------------------------------------------------------

//initialize the port for use.
initport(fd);

char received[READ_BYTES+1];

while (1)
{
//printf("--------------------------------------------------------------------------\n");
find_sync_bytes(fd);
readport(fd,received);
print_str_to_hex(received);                //print the string in hex form.
}
//-----------------------------------------------------------
//close the serial port.
close(fd);
return 0;
}

Code:

int readport(int fd, unsigned char *result){
        int new_bytes,bytes_read_tot;
        new_bytes=0;
        result[0]=0x00;        //clear buffer before reading it.

        new_bytes = read(fd,result,READ_BYTES);
        printf("new_bytes: %d\n",new_bytes);
        if(new_bytes<0){
                        if(errno == EAGAIN){
                                printf("SERIAL EAGAIN ERROR\n");
                                return 0;
                        }       
                        else{
                                printf("SERIAL read error %d %s\n",errno,strerror(errno));
                                return 0;
                        }
                }//end if.
//        }//end for.
        result[new_bytes] = 0x00;        //terminate string.
        //result[bytes_read_tot] = 0x00;        //terminate string.

        return 1;
}//end readport function.

int initport(int fd){
        struct termios options;
        tcgetattr(fd, &options);        //get the current options for the port.
        cfsetispeed(&options, B115200);        //set baud rate for input port.
        cfsetospeed(&options, B115200);        //set baud rate for output port.

        //enable the receiver and set local mode.
        options.c_cflag |= (CLOCAL | CREAD);

        options.c_cflag &= ~PARENB;
        options.c_cflag &= ~CSTOPB;
              options.c_cflag &= ~CSIZE;
        options.c_cflag |= CS8;

        //raw input set.
        options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

        //set the new options for the port.
        tcsetattr(fd, TCSANOW, &options);

        return 1;       
}//end initport function.

void print_str_to_hex(unsigned char *char_string){
        int i;
        printf("hex representation:\n");
        for(i=0;char_string[i]!=0x00;i++){
                printf("%02X ",char_string[i]);       
        }//end for.
        printf("\n");
}//end of str_to_hex function.

int find_sync_bytes(int fd){
        int read_count =0;                //initialize read count to zero.
        int sync_count =0;                //initialize sync characters to zero.
        int in_sync =0;                        //assume that the buffer is not yet insync.
        unsigned char buffer[10];
        //while four sync bytes have not been read and max read count has not been exceeded...
        while((read_count<MAX_TRIES) && (sync_count<4)){
                buffer[0]=0x00;                //set first element to \0.
                read(fd,buffer,1);        //read and store a single byte.
        if(buffer[0]==0xFF)                //if char is sync char...
                sync_count++;
        else
                sync_count=0;
        if(sync_count==4)                //if sync count is four...
                in_sync=1;                //raise in_sync flag.
        else
                in_sync=0;                //otherwise keep the flag low.
        read_count++;
        }//end while.
        if(read_count>=MAX_TRIES)
                printf("Can't find sync characters.\n");        //let user know can't find sync chars.
return 0;
}//end find_sync_bytes function.


Wim Sturkenboom 08-05-2008 11:12 AM

Your print routine will only print till it finds 0x00. Any chance that that occures in the received data as well? If so, it explains the problem where you only print e.g. 13 hex values.

As binary data can contain any value from 0x00 to 0xFF, I would not use your approach for the print function but pass a length as well.

If you want to make sure that you receive 34 bytes, you must read (in a loop) till you've got 34

Code:

newbytes=0;
do
{
    newbytes+=read(fd,&result[newbytes],READ_BYTES);
} while(newbytes<34);

You need to polish it as you might get 33, next 7 making a total of 40 and your result buffer might be smaller.

And last but not least, your transmitting side might do some funnies as well like sending 33 bytes and placing the last byte in the next packet or not transmitting it at all.


All times are GMT -5. The time now is 04:31 AM.