2
votes

This is the code given by http://www.gravitech.us/7segmentshield.html.

void SerialMonitorPrint (byte Temperature_H, int Decimal, bool IsPositive)
{
Serial.print("The temperature is ");
if (!IsPositive)
{
  Serial.print("-");
}
Serial.print(Temperature_H, DEC);
Serial.print(".");
Serial.print(Decimal, DEC);
Serial.print(" degree C");
Serial.print("\n\n");
}

But when I try to read data from serial port, I found that I read data character by character.

UPDATE

while(1)
{
    char buffer[100];
    int chars_read = read(fd, &buffer, sizeof(buffer));
    buffer[chars_read] = '\0';
    printf("%s", buffer);
}

So how can I read line by line?

3
Aren't you reading an entire buffer (100 bytes) worth of data ? BTW, you should check the return value of read() which is going to tell you how many bytes were read successfully into the buffer and need not always be the size of the buffer. And before printing you would want to add a '\0` character in the buffer after this size. Also what kind of data you expect to read over the serial port - just text or hexadecimal values ?Tuxdude
@Tuxdude: like "The temperature is 28.53 degree C". Actually, the return value of read() is 1.Cacheing
Have you not tried using fgets or similar? You'd need to set up a file stream to fd for that.teppic
@teppic: do you mean use fgets to replace read?Cacheing
@teppic - for a serial port, it is much easier to use unbuffered I/O rather than buffered I/O using fgets. Also if there is any EOF character from the serial port - fgets will get confused and will stop reading data.Tuxdude

3 Answers

3
votes

You can't guarantee that a single call to read will give you exactly one line of text. You need to buffer the data. The easiest way to do this is to read exactly one character at a time, and stop when you reach a newline character. If you want to read as many characters as possible each time, the buffering code becomes more complicated.

Try this to start:

char buffer[100] = {0};
int pos = 0;

while( pos < 99 ) {
    read(fd, buffer+pos, 1);           // Note you should be checking the result
    if( buffer[pos] == '\n' ) break;
    pos++;
}

// Normally you would null-terminate string, but noticed I initialised the
// buffer to all zeroes at the beginning.  So this is not strictly necessary.
// However, in this case it will remove the newline character.
buffer[pos] = 0;
3
votes

The while loop does not necessarily read character by character, but it might return you one character at a time for each read based on the serial port device and the rate of transmission.

I've made some changes to fix few bugs in your while loop:

while(1)
{
    char buffer[100];
    ssize_t length = read(fd, &buffer, sizeof(buffer));
    if (length == -1)
    {
        printf("Error reading from serial port\n");
        break;
    }
    else if (length == 0)
    {
        printf("No more data\n");
        break;
    }
    else
    {
        buffer[length] = '\0'
        printf("%s", buffer);
    }
}

List of changes:

  • Check the return value from read
  • I'm assuming when read fails or returns 0, it means no more data to read and breaks the while loop execution. Modify this behavior as per your needs.
  • Append a '\0' character before printing, otherwise printf would be printing garbage values in the buffer.

Comments:

  • Do not worry about lines, the read should return a \n character in the buffer which printf would interpret as a newline when you print it out.
  • If you're actually only interested in grabbing a line and storing it somewhere, you need to read and append to another buffer until you get a \n in the buffer, and also need to handle multiple \n within the same buffer implying multiple lines.
0
votes

Probably you have to implement that by yourself. Just keep reading character by character until you reached '\n', and return what you have read.

I didn't check, but I suspect that's how 'readline' is usually implemented.