Multiple serial coms on STM32F401RE

Been trying to get my Nextion screen to talk to my ST board. This is the multi-serial example and works fine.

import streams

s0=streams.serial(SERIAL0,set_default=True)
# s1=streams.serial(SERIAL1,baud=9600) ## define second serial port

while True:
    print("Write some chars on the serial port and terminate with \\n (new line)")
    line=s0.readline() # read and return any single character available on the serial port until a \n is found
    print("You wrote:", line)
    print()
    sleep (300)

However if I uncomment the line that defines stream “s1” (on serial1) then the program no longer works. It compiles and runs, but the first print command is never executed. The program just hangs. What do I have to do to talk to multiple serial ports?
I’m a bit confused with the documentation too. According to the STM documentation for the board there are two serial ports on the STM32F401RE; USART2 on pins PA2 (D0) and PA3 (D1), (the default ones for connecting to the PC via USB) and USART3 on pins PC10 (D41) and PC11 (D42). The Zerynth pinmap shows three serial ports: on D0 and D1, D24 and D25, and D8 and D2. Who is right?

Any suggestions?
Thanks, Ian

Hi @mogplus8
As for the code, if you defined multiple streams, I think you need to define which stream output it should use.
For instance:

import streams
streams.serial()

s0=streams.serial(SERIAL0,set_default=True)
s1=streams.serial(SERIAL1,baud=9600) ## define second serial port

while True:
    print("Write some chars on the serial port and terminate with \\n (new line)",stream=s0)
    line=s0.readline() # read and return any single character available on the serial port until a \n is found
    print("You wrote:", line,stream=s0)
    sleep (300)

Try this code and let me know if it still hangs.

As for the pin-maping, Please use the Zerynth pinmap according to each uart instance, As these modifications are made due to other restrictions in the Zerynth VM. :smile:

Thanks @karimhamdy1. I did have that format in some of my testing, then discovered the set_default option. Using that means it isn’t necessary to add the stream= parameter to output for stream s0 as it is the default stream for serial output.
Interesting about the pin mapping, especially given that Zerynth has three serial ports while the board itself has only two defined for it. I’ll do some experimenting when I can get something to work!
What I have discovered though it that if I define s1 before s0 the program will work, in that the first print is executed and it reads input and prints it back to the serial monitor. It still won’t read the input stream, but s1.available does return the length of the input read, as shown in this screenshot.


This version of the program produces the result shown. To get this I start the program, then tap the button on the Nextion screen (connected to Serial1), then enter a string in the input area of the serial monitor and hit Enter. The result is that the input string is printed, then the length of the string read from Serial1, then the program hangs on the s1.readline() command. If I comment it out (and remove mystring from the print command) the program runs and displays the “Write some chars…” message again. So, the readline() command fails, but I have no idea why.
I can also confirm that the Zerynth pinmap appears to be correct. I tried both Serial1 and Serial2 and they both work, in that available() works. readline() doesn’t work for either of them.
Trying some more experiments.
:wink: Ian
EDIT. I’ve learned that serial read blocks. i.e. stops the program. That might have something to do with it…

Well I finally got it to work!


Note that readline() works fine for serial0. I couldn’t get it to work for either serial1 or serial2. Also note that it is necessary to define serial0 last. If it is not last serial defined the program compiles but does not start. (the first print command is never executed).
For this test I tapped button 1 on my Nextion, then entered “button 1” in the serial monitor. The program reads and displays the correct characters. 0x65 means a touch event occurred. 0x00 means it was on page 0. 0x02 means it is the second control defined on page 0. 0x00 means it was a button release (not a button press). The last three 0xFFs are terminator characters sent at the end of every message from the screen.
For the next one I touched button 2 and then entered “button 2” in the serial monitor. Note the same message was returned by the screen, but now the control id is 0x03 which is the id for the second button on page 0, not 0x02. So everything is working correctly.
I ended up using the read() method for reading the bytes, which works fine, and does basically the same thing as readline() but the latter has a few more features.

So, all good. :slight_smile: :sweat_smile:

This is strange, We’ll have a look at this.

Awesome, I am glad It worked eventually! :smile: