5 years, 8 months ago.

UART does not return full strings

I'm making a test app with NUCLEO-L053R8 on mbed. I have some trouble.

My code is here.

#include "mbed.h"

Serial pc(SERIAL_TX, SERIAL_RX);
Serial self_uart(PA_9,PA_10); // tx, rx

int main() {
    volatile char command[8]; 
    unsigned int i = 0;

    pc.printf("Start!\r\n");
    self_uart.baud(115200);

    while(1) {
        i = 0;
        self_uart.printf("hogehoge\r\n");
        while(self_uart.readable()==0){
            pc.printf("waiting\r\n");
            wait(0.1);
        }; 
        pc.printf("data received\r\n");

        while(self_uart.readable()>0) {
            pc.printf("i=%d\r\n", i);
            command[i] = self_uart.getc();
            i++;
            wait(0.1);
        }
        pc.printf("%s\r\n", command);
        wait(2.0); // 1 sec
    }
}

PA_9 is connected to PA_10 so when self_uart send a message "hogehoge", the device itself receives the message.

The result is below.

Start!
data received
i=0
h

test
data received
i=0
h

test
data received
i=0
h

Only "h" returned, while "hogehoge" should have been returned.

Why? I spent a lot of time to solve this problem. Please help me!

Yusuke,

Have you tried a lower baud rate below 115200 ?

posted by Kevin Braun 20 Aug 2018

Hello Yusuke-san,

I have run your code on an LPC1768 and it worked fine. However, since

self_uart.printf("hogehoge\r\n");

sends 10 characters, the command variable shall be sized adequately (+ one byte for the null termination character. See below why):

volatile char command[11]; 

Otherwise when i > 7

command[i] = self_uart.getc();

would write to undefined memory location and the program could crash.

Also when a c-style string is printed with printf the string shall be null terminated as below:

        while(self_uart.readable()>0) {
            pc.printf("i=%d\r\n", i);
            command[i] = self_uart.getc();
            i++;
            wait(0.1);
        }
        command[i] = '\0';             // terminate the string with null character
        pc.printf("%s\r\n", command);  // so printf is able to figure out how long the command string is
posted by Zoltan Hudak 20 Aug 2018

1 Answer

5 years, 8 months ago.

Hi Yusuke,

I believe you can read this article written in Japanese. It says implementation of Serial class doesn't have software buffer. If you use printf() to send a message, it cause overflow because the program send all the characters before receive.

According to Zoltan, your program worked on LPC1768. This is because LPC1768 has 16-byte hardware buffer. https://exploreembedded.com/wiki/LPC1768:_UART_Programming

I changed your code not to require buffer. This worked on NUCLEO-L053R8.

#include "mbed.h"
 
Serial pc(SERIAL_TX, SERIAL_RX);
Serial self_uart(PA_9,PA_10); // tx, rx

const char message[] = "hogehoge\r\n";
 
int main() {
    volatile char command[11]; 
    unsigned int i = 0;

    pc.baud(115200);
    pc.printf("Start!\r\n");
    self_uart.baud(9600);
 
    while(1) {
        i = 0;
        char *p = (char*)message;

        do{
            self_uart.putc(*p++);
            while(!self_uart.readable()) continue;
            command[i++] = self_uart.getc();
        } while(*p != '\0');

        command[i] = '\0';

        pc.printf("%s\r\n", command);        
        wait(2.0); // 1 sec
    }
}

Accepted Answer

Osamu Koizumi

Thank you so mucn! the code works!

posted by Yusuke Fukuhara 21 Aug 2018

Hi, Osamu Koizumi If possible, could you show code in which NUCLEO-L053R8 communicate with another device through UART? I want to know how to write code sending and receiving data. If you tell it, it is really helpful.

posted by Yusuke Fukuhara 22 Aug 2018

Hi Yusuke,

Do you want to communicate between two Mbed devices? Check this FAQ: https://os.mbed.com/questions/77669/UARTshort-int-mbedmbed/

posted by Osamu Koizumi 23 Aug 2018

No, I want a mbed device to communicate with a 3g module, like Sierra wireless HL8548, through UART.

Mbed device ーーAT command ーー> HL8548

Mbed device <ーーresponse ーーーー HL8548

Do you know how to do this?

posted by Yusuke Fukuhara 23 Aug 2018

If you use AT command to communicate with your modem, see ATCmdParser. The example in this page uses serial and AT command.

posted by Osamu Koizumi 23 Aug 2018

Thank you so much for telling the command ATCmdParser!

I connected NUCLEO-L053R8 and eps8266 through UART.

I implemented the below code, which should get SDK version, but it does not work. SDK version does not show the correct value. Instead, SDK version = 0.0.0

I'm new to mbed and confused.

Could you tell me where is the mistake, if you find it?

my code

#include "mbed.h"
#include "ATCmdParser.h"
Serial pc(SERIAL_TX, SERIAL_RX);
 
int main() {
    pc.printf("Hello World!\r\n");
    UARTSerial serial = UARTSerial(PA_9,PA_10);
    ATCmdParser at = ATCmdParser(&serial, "\r\n");
    int value1 = 0;
    int value2 = 0;
    int value3 = 0;
    
    while(1){
        pc.printf("start\r\n");
        at.send("AT+GMR") && at.recv("SDK version:%d.%d.%d", &value1, &value2, &value3) && at.recv("OK");
        pc.printf("SDK version:%d.%d.%d\r\n", value1, value2, value3); // version should be 2.0.0
    }
}
posted by Yusuke Fukuhara 23 Aug 2018

If you are using ESP-WROOM-02 Shield, this code should work.

#include "mbed.h"
#include "ATCmdParser.h"
Serial pc(SERIAL_TX, SERIAL_RX);
 
int main() {
    pc.printf("Hello World!\r\n");
    // (*) Please wire D8 and D4 on ESP-WROOM-02 Shield
    //     and toggle the hardware switch on the shield to SW
    UARTSerial serial = UARTSerial(PA_9,PA_10, 115200);
    // Set D4 as a input for protection
    DigitalIn pin_d4(D4);
    ATCmdParser at = ATCmdParser(&serial, "\r\n");
    int value1 = 0;
    int value2 = 0;
    int value3 = 0;
    
    while(1){
        pc.printf("start\r\n");
        at.send("AT+GMR") && at.recv("SDK version:%d.%d.%d", &value1, &value2, &value3) && at.recv("OK");
        pc.printf("SDK version:%d.%d.%d\r\n", value1, value2, value3); // version should be 2.0.0
        wait(1);
    }
}

By the way, if you use ESP8266, device driver already exists. Check it out: https://github.com/ARMmbed/esp8266-driver

posted by Osamu Koizumi 24 Aug 2018

I'm using this: http://akizukidenshi.com/catalog/g/gK-09758

Is this ESP-WROOM-02 Shield?

And if not, how to communicate between a mbed device and the above wifi device? Is ATCmdParser available?

posted by Yusuke Fukuhara 24 Aug 2018

That is different from ESP-WROOM-02 Shield: https://www.switch-science.com/catalog/2619/ However, the difference is just pinout. You should be able to do the same thing with your hardware.

posted by Osamu Koizumi 24 Aug 2018

The code works! I had a pin assignment mistake. Thanks a lot!

posted by Yusuke Fukuhara 24 Aug 2018