6 years, 3 months ago.

How to read and write serial data

Hi all,

I'm a little bit confused about something that in my head should be pretty simple.

Basic idea is that I have a button and an LED. When I send a "1" over the serial port, the LED turns on and when I send a "0" the LED turns off. This bit works just fine, nice and easy.

However, I also simultaneously want the mbed to send a character back up the serial connection when the button gets pressed.

I can make each work independently, but when I try and combine the code the only bit that works is the sending of commands down to the mbed. The code looks like this:

#include "mbed.h"

DigitalIn   btn(p20);
DigitalOut  led(LED3);
Serial      pc(USBTX, USBRX);

int main() {    
    while (true) {
        char c = pc.getc();
        if(c == '1') {
            led = 1;
        }
        if(c == '0') {
            led = 0;
        }
        if(btn == 1) {
            pc.printf("b");
        }
    }
}

My assumption is that something is going on here that's blocking the last if statement from executing. I experimented with threads - essentially having one thread for the reading and another for writing. However that seemed to get me into more trouble.

Any ideas? This seems like it should be pretty simple.

Thanks, Dan

2 Answers

6 years, 3 months ago.

Hello Daniel,

The program is waiting for a char to be received over the serial line when executing the statement
char c = pc.getc();
You can verify it by running the following code:

#include "mbed.h"

Serial pc(USBTX, USBRX);

int main()
{
    while (true)
    {
        pc.printf("Waiting for a char on serial line.\r\n");
        char c = pc.getc();
        pc.printf("'%c' received.\r\n", c);
    }
}

To avoid blocking, call the pc.getc() function only when a char has been received, for example as follows:

#include "mbed.h"

DigitalIn       btn(USER_BUTTON);
DigitalOut      led(LED1);
Serial          pc(USBTX, USBRX);
volatile char   c = '\0'; // Initialized to the NULL character

void onCharReceived()
{
    c = pc.getc();
}

int main()
{
    pc.attach(&onCharReceived);

    while (true)
    {
        if (c == '1')
        {
            c = '\0';  // To avoid execution of this block until a '1' is received again.
            led = 1;
        }

        if (c == '0')
        {
            c = '\0';  // To avoid execution of this block until a '0' is received again.
            led = 0;
        }

        if (btn == 0)
        {
            pc.printf("b");
        }
    }
}

Accepted Answer

Thanks a lot! This works fine in conjunction with Bill's suggestion below.

posted by Daniel Knight 29 Jan 2018

Is there a way to access the stdin/out Serial object so we can call attach on it? I'm using getchar()/putchar() now but I'd like to use something like stdin.attach(onCharReceived) with stdin being the "default" Serial link created by Mbed OS.

posted by Matthieu Labas 01 Apr 2019
6 years, 3 months ago.

The other recommendation would be use printf with a RawSerial declaration instead since Serial will buffer until "\r\n" is received or until the transmit buffer is full.

Instead declare your serial as

RawSerial      pc(USBTX, USBRX);

Then you can happily use printf for single character transmission.

Another method would be to replace

pc.printf("b");

with

pc.putc('b');

Using putc will transmit the character immediately.