std/uart — Serial USART¶
import std/uart
Blocking, polled access to the USART for asynchronous serial I/O. Each operation busy-waits on the relevant status flag, so there is no buffering and no interrupt handling in this module.
Configuring the baud rate¶
@uart_init takes the UBRR divisor value, not a baud rate. That is
why the examples pass a number like 103 rather than 9600: 103 is the
divisor that produces 9600 baud on a 16 MHz clock. Compute it from your clock
and desired baud with:
For 16 MHz at 9600 baud: 16000000 / (16 * 9600) - 1 = 103.
Common values (rounded to the nearest integer) for the two most common clocks:
Baud rate |
UBRR at 8 MHz |
UBRR at 16 MHz |
|---|---|---|
2400 |
207 |
416 |
4800 |
103 |
207 |
9600 |
51 |
103 |
19200 |
25 |
51 |
38400 |
12 |
25 |
57600 |
8 |
16 |
115200 |
3 |
8 |
The further the real divisor is from a whole number, the larger the baud-rate error; the slower rates above are exact, while 57600/115200 carry a few percent error that most receivers still tolerate.
USART0¶
- @uart_init($ubrr: u16)¶
Initialise USART0: set the baud divisor
$ubrrand enable the transmitter and receiver in 8-N-1 frame format.
- @uart_send($data: u8)¶
Transmit one byte, blocking until the transmit data register is empty first.
- @uart_receive() -> u8¶
Block until a byte has been received, then return it.
- @uart_available() -> u8¶
Return non-zero if a received byte is waiting to be read,
0otherwise. Use this to poll without blocking in@uart_receive.
- @uart_print_str($s: str ram)¶
Transmit a NUL-terminated string from RAM, one byte at a time, stopping at the terminating
0. Each byte is sent through@uart_send, so the call blocks until the whole string has been pushed out.
- @uart_print_char($char: u8)¶
Convenience wrapper that transmits a single character
$char.
- @uart_println()¶
Send a carriage return (13) followed by a line feed (10) — a CRLF line terminator.
- @_uart_wait_tx()¶
Internal: block until the transmit register is ready. Used by the public send routines.
Additional USART instances¶
Devices with more than one USART expose the same API on numbered modules. The
uart1 … uart5 families mirror USART0 exactly, for use on parts that have
those peripherals:
@uart1_init/@uart1_send/@uart1_receive/@uart1_available/@uart1_print_str/@uart1_print_char/@uart1_println@uart2_*,@uart3_*,@uart4_*,@uart5_*— identical shape.
Only call into an instance that exists on your target.
Example¶
target atmega328p
import std/uart
@main {
@uart_init(103) # 9600 baud @ 16 MHz (UBRR = 103)
@uart_print_str("ready\r\n") # greet over the serial line
loop * {
? @uart_available() != 0 { # is a received byte waiting?
ram imut $c: u8 = @uart_receive() # read it (blocks until one arrives)
@uart_send($c) # echo the same byte back out
}
}
}