Serial Theory
The micro:bit core crate implements the embedded_hal::serial::Write and embedded_hal::serial::Read traits for the tx and rx pins respectively.
writeln!
and Carriage Return
In the introduction page on serial communication, I brushed over this:
# #![allow(unused_variables)] #fn main() { // Write string with newline and carriage return let _ = write!(tx, "serial test\r\n"); #}
A naïve assumption would be to try the seemingly more correct writeln!
macro:
# #![allow(unused_variables)] #fn main() { // Write string with newline and carriage return let _ = writeln!(tx, "serial test"); #}
This will usually fail to do what is intended, as multiple writes will only print one line in PuTTY, and produce the following in minicom:
serial test
serial test
serial test
serial test
Your choices are to either configure minicom and PuTTY appropriately or use write!
with \r\n
.
Control Characters
The control characters operate based on a print head, as used in teleprinters.
\r
- Carriage Return - The print head is moves left to the start of the line.
\n
- Line Feed - The print head moves down once to a new line.
writeln!
macro
The writeln!
macro should append a new line,
but he documentation for core::writeln says:
On all platforms, the newline is the LINE FEED character (\n/U+000A) alone (no additional CARRIAGE RETURN (\r/U+000D).
minicom
CTRL-A + Z will tell you that CTRL-A + U will add a carriage return.
This will add a carriage return to a received \n
PuTTY
In PuTTY, you can enable enable Implicit LF in every CR
under Terminal options.
Blocking
Behind the scenes, embedded_hal::serial
uses the nb crate to allow for blocking and non-blocking operation.
This is implemented in embedded_hal crates by returning nb::Error::WouldBlock
when a read or write action cannot be performed immediately.
In this chapter, we will only be using read and write as simple blocking calls.
block!
The block!
macro provided by the crate continuously calls the expression
contained until it no longer returns Error::WouldBlock.
Tx - embedded_hal::serial::Write
or core::fmt::Write
The write!
and writeln!
macros call write_str
of the core::fmt::Write
trait which is implemented for Tx.
write_str
is implemented as a blocking call to write
of the embedded_hal::serial::Write
trait.
This means write!(tx, "a")
is equivalent to block!(tx.write(b'a'))
.