Reputation: 148
I have an instrument which I need to talk to by RS232. I am using C and following is the code. The problem is that, when I try to read field value (reading from meter) which is 11 byte long, one read command is reading only 8 bytes and subsequently I have to issue another read command which gives me final 3 bytes. Finally I am concatenating both read buffers to make final meaningful value.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXWAIT 30
#define BAUDRATE B9600
#define TESLAMETER "/dev/ttyS0"
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1
#define NOREAD 255
volatile int STOP = FALSE;
int fd;
struct termios oldtp, newtp;
int openComPort(void)
{
fd = open(TESLAMETER, O_RDWR | O_NOCTTY |O_NDELAY );
if (fd <0)
{
perror(TESLAMETER);
return fd;
}
else
fcntl(fd,F_SETFL,0);
tcgetattr(fd,&oldtp); /* save current serial port settings */
bzero(&newtp, sizeof(newtp));
newtp.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
newtp.c_iflag = IGNPAR | ICRNL;
newtp.c_oflag = 0;
newtp.c_lflag = 0;//ICANON;
newtp.c_cc[VINTR] = 0; /* Ctrl-c */
newtp.c_cc[VQUIT] = 0; /* Ctrl-\ */
newtp.c_cc[VERASE] = 0; /* del */
newtp.c_cc[VKILL] = 0; /* @ */
newtp.c_cc[VEOF] = 4; /* Ctrl-d */
newtp.c_cc[VTIME] = 1; /* inter-character timer unused, 0.5 seconds read timeout */
newtp.c_cc[VMIN] = 0; /* blocking or non blocking read until 1 character arrives */
tcflush(fd, TCIFLUSH);
tcsetattr(fd,TCSANOW,&newtp);
return fd;
}
float readMagField()
{
unsigned char cmd[]="FA0\r"; // Read Field
char buff2[11] = {0x00};
char buff3[11] = {0x00};
float fieldFloat = 0.00;
int n_written= 0, spot = 0, res;
do
{
n_written = write( fd, &cmd[spot], 1 );
spot += n_written;
} while (cmd[spot-1] != '\r' && n_written > 0);
if (n_written < 0)
{
printf("write() of 4 bytes failed!\n");
return FALSE;
}
else
{
//printf("Field Read Command sent successfully %d\n",n_written);
res = read(fd,buff2,11); // Reads 8 bytes
res = read(fd,buff3,11); // Reads remaining 3 bytes
fieldFloat = atof(strcat(buff2,buff3)); // Final string of 11 bytes here
return fieldFloat;
}
}
Is there something that I am doing or setting wrong? Because, I can read the complete set of characters in one go using Python serial module, but not in C. I am working on Ubuntu 12.04 LTS.
Upvotes: 2
Views: 1119
Reputation: 75062
read()
may return without reading the specified length.
RETURN VALUE
On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of- file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal. See also NOTES.
How about retrying until the desired length of data have been read?
ssize_t read2(int fd, void *buf, size_t count) {
ssize_t read_length = 0;
while (read_length < count) {
ssize_t delta = read(fd, buf + read_length, count - read_length);
if (delta == -1) return -1;
read_length += delta;
}
return read_length;
}
Upvotes: 2