2 years ago.

Serial (UART) on STM32F411RE Rx not working

Hi,

I've been trying to get F411RE microcontroller talking to my ESP8266 WiFi module. At first I thought the module wasn't receiving characters properly however on further inspection with the onboard CH430 USB->TTL chip it seems that the module was indeed responding to the AT commands properly. I had a bit of code that looked like this:

#include "mbed.h"

DigitalOut led(LED1);
DigitalOut espRST(D3);
Serial pc(USBTX, USBRX);
Serial esp(D8, D2);

int main(){
    esp.baud(115200);
    espRST = 0;
    espRST = 1;
    wait_ms(100);

    pc.printf("Hello World !\n");
    esp.printf("AT+RST\r\n");
    char ch;

    while(1) {
        wait(0.5); // 1 second
        led = !led; // Toggle LED
        
        pc.printf("Sending AT command");
        esp.printf("AT\r\n");
        wait_ms(100);
        pc.printf("Written\n");
             
        while(esp.readable()){
            pc.printf("ESP can be read!\n");
            ch = esp.getc();
            pc.printf("%c", ch); 
        }
        pc.printf("\n");
    }
}

As you might expect, that resulted in this output in the ESPlorer tool:

/media/uploads/TheBates/esplorer_output.jpg

However I couldn't see "ESP can be read" appear in TeraTerm. I thought I'd try a loopback test to verify that the Rx on the board was working by connecting D8 to D2 (Tx to Rx) and running the program above. However it still wasn't reading out the "AT" characters.

After now many hours of moving code around trying to get it working this code produces some results:

#include "mbed.h"

DigitalOut led(LED1);
Serial pc(USBTX, USBRX);
Serial esp(D8, D2);

esp.baud(115200);

pc.printf("Hello World !\n");

 while(1){
        char msg[] = {"Hello"};
        esp.printf("%s", msg);
        ch = esp.getc();
        pc.printf("UART: %c\n", ch); 
        ch = esp.getc();
        pc.printf("UART: %c\n", ch); 
        ch = esp.getc();
        pc.printf("UART: %c\n", ch);
        ch = esp.getc();
        pc.printf("UART: %c\n", ch); 
}

It seemed like calling "esp.readable()" was never returning true so I thought just forcibly reading it character by character may produce some results. It does. It only reads the last (first? - byte ordering issue?) two characters 'l' and 'o' before blocking on the third read. I tried the "readable()" function with the PC serial port (Serial 2, I believe) to echo characters back into a terminal. That seemed to work so could it just be a Serial1 issue? I haven't tried the loopback test on the Morpho pins yet as I'm waiting for some female-to-female cables to arrive.

Has anyone else come across this issue? Or can anyone see a glaring issue with my code? Any assistance with this issue would be much appreciated!

Thanks, Russell Bateman

Comment on this question

2 Answers

2 years ago.

Make two changes, 1: have the PC serial port running at the same speed or ideally faster than the one to the radio so that it's not a bottleneck otherwise you can miss incoming data while sending data out. And secondly read the data as it arrives not after a time delay so that there is no danger of the receive buffer overflowing. e.g.

#include "mbed.h"
 
DigitalOut led(LED1);
DigitalOut espRST(D3);
Serial pc(USBTX, USBRX);
Serial esp(D8, D2);

void onRadioRx(void) {
  while (esp.readable()) // just in case more that 1 byte arrives 
    pc.putc(esp.getc());
}
 
int main(){
    pc.baud(115200);
    esp.baud(115200);
    espRST = 0;
    wait_ms(10);
    espRST = 1;
    wait_ms(100);
 
    pc.printf("Hello World !\n");
    wait_ms(10); // give the PC tx buffer time to clear...

    pc.attach(&onRadioRx); // every time data arrives call this function.

    while(1) {
        led = !led; // Toggle LED
        pc.printf("Sending AT command\r\n");
        wait_ms(10);
        esp.printf("AT\r\n");
        wait(0.5); 
    }
}

The alternative is to replace the serial port object with one of the many buffered serial port libraries around, they will handle reading from the hardware buffers in the background and put things into a software buffer. This uses up memory and has a slight performance hit but that way your software doesn't need to worry about baud rates or buffer overflows.

Hi Andy, thanks for the in depth response. Unfortunately your example had provided similar results to what I was trying yesterday. Essentially only the first byte would be received by the RX handler for some reason.

However as you suggested, the BufferedSerial library has proved much better and I'm getting "OK"'s back from the ESP! At this point in my project I think I'll take the additional overhead. Perhaps at some point I'll go through that code to see what its doing differently to try and reduce memory consumption.

Thanks, Russell Bateman

posted by Russell Bateman 06 Nov 2017
2 years ago.

Why are there two espRST and both of it has different values ?

Are you talking about lines 10 & 11 of the first example? That's to toggle the Reset pin on the D1 Mini board to do a hardware reset.

posted by Russell Bateman 05 Nov 2017

You should put a short pause between reset = 0 and reset = 1, most parts have a minimum reset low time. Around 10ms or so is probably enough but check the part data sheet to be sure.

posted by Andy A 06 Nov 2017