UART is a type of serial interface, as opposed to a parallel interface. A parallel interface can work at higher speeds but the disadvantage is that it needs multiple input/output lines. Other examples of serial interfaces are SPI and I2C.
Supported Devices
At the moment only following devices are supported. I might add more in the
feature. It might work for other similar devices not listed below.
- C8051F330
Contents
- UART Characteristics
- Library Structure
- Using UART library
- Initialization function
- Send a byte
- Send a string
- Send bytes
- Send integer number
- Send float number
- Send hex numbers
- Check for new received data
- Wait for transmission complete
- Read a byte
- Read bytes
- Read bytes until
- Disable UART
- Flush
- Redirect received data
- Code example
- Download
UART Characteristics
Frame format
A serial frame is composed of a character of data bits with
synchronization bits (start and stop bits). 8-Bit UART mode uses a total of 10
bits per data byte: one start bit, eight data bits (LSB first), and one stop
bit.
A frame starts with the start bit, followed by 8 data bits (LSB first). When a complete frame is transmitted, it can be directly followed by a new frame, or the communication line can be set to an idle (high) state. The figure below illustrates the frame format:
IDLE: No transfers on the communication line (Rx or Tx). An IDLE line must be high.Start Bit: always low.
(D): Data bits (0 to 7).
Stop Bit: always high.
The Stop bit can be followed by a Start bit (low) for another frame, or Idle (high). All devices connected to the UART bus must use the same frame format and baud rate.
Baud Rate
The baud rate specifies how fast data is sent over a serial line. It's usually expressed in units of bits-per-second (bps). Most commonly used baud rates are 9600 and 115200 bps.
"The UART0 baud rate is generated by Timer 1 in 8-bit auto-reload mode. The TX clock is generated by TL1; the RX clock is generated by a copy of TL1 (shown as RX Timer in Figure 16.2), which is not user- accessible. Both TX and RX Timer overflows are divided by two to generate the TX and RX baud rates. The RX Timer runs when Timer 1 is enabled, and uses the same reload value (TH1). However, an RX Timer reload is forced when a START condition is detected on the RX pin. This allows a receive to begin any time a START is detected, independent of the TX Timer state." from C8051F330 datasheet chapter 16.
Wiring
Lets say you want to interface UART 0 with a device that has this pins: RX and
TX. Then you connect RXD0 to TX and TXD0 to RX. Also they must share a common
ground.
For most Silicon Labs microcontrollers the TX/RX pins are as follows:
TX0 on P0.4, RX on P0.5
Check the datasheet for your specific device to ensure the pins are correct.
Library Structure
The file uart.h defines some user settings that can be modified accordingly.
TX and RX buffers
Transmitted and Received data are buffered in two circular arrays that by
default have a size of 16 bytes each. The size can be from 1 to 255 bytes.
Having a larger array can be a bit faster. When using higher baud rates it is
recommended a bigger buffer to avoid loosing incoming data and to give more
time for the microcontroller to process the data.
#define UART_TX_BUFFER_SIZE 16 #define UART_RX_BUFFER_SIZE 16
CPU clock frequency - SYSCLK
#define SYSCLK 24500000UL
SYSCLK defines the processor clock frequency in Hertz and is used to calculate the timeout in some functions.
SYSCLK is best to be defined inside project properties in Simplicity Studio
(or your particular IDE) or a Makefile if custom Makefiles are used. See
https://www.programming-electronics-diy.xyz/2024/03/defining-sysclk-or-fcpu-in-simplicity.html.
Using UART library
Initialization function
Sets TX, RX pins and the crossbar. Configures UART and Timer 1. Sets the baud rate, enables UART interrupts and global interrupts.
void UART_init(int32_t sysclk, int32_t baudrate)
Parameters
sysclk
System clock in Hertz, SYSCLK also known as F_CPU.
baudrate
Desired baud rate. Some standard values are: 9600, 14400, 19200, 38400,
57600, 115200, 128000 and 256000.
Usage:
UART_init(SYSCLK, 115200);
Send a byte
Puts a byte of data in the transmit buffer and enables the transmit interrupt.
uint8_t UART_send(uint8_t data)
Parameters
data
The data byte.
Return: 0 on success, 1 on failure.
Usage:
// Send 'A' ASCII character UART_send('A'); // Send '3' ASCII symbol UART_send('3'); // Send number of the '3' ASCII symbol UART_send(51);
Send a string
Send a null terminated string.
uint8_t UART_sendString(char* s)
Parameters
char* s
A string of characters.
Return: 0 on success, 1 on failure.
Usage:
UART_sendString("Sent from UART0"); // Or using the '\n' character to start a new line in a serial terminal. UART_sendString("Sent from UART0\n");
Send bytes
Send a series of bytes in a buffer.
uint8_t UART_sendBytes(uint8_t* buff, uint8_t length)
Parameters
uint8_t* buff
Pointer to a byte array.
uint8_t length
Length of the array.
Return: 0 on success, 1 on failure.
Usage:
const uint8_t bufferSize = 20; uint8_t buff[bufferSize]; // bufferSize argument can be smaller to // send only first few bytes UART_sendBytes(buff, bufferSize);
Send integer number
Convert an integer number into a string array and send it over UART.
void UART_sendInt(INT_SIZE number)
Parameters
INT_SIZE number
INT_SIZE is defined in the "utils.h" file, and can be int32_t or int64_t
Send float number
Convert a float number into a string array and send it over UART.
void UART_sendFloat(float number, uint8_t decimals)
Parameters
float number
A float number.
uint8_t decimals
Number of digits after the dot.
Send hex numbers
Convert a 1- 2- or 4-byte integer number into hexadecimal value and send it over UART.
void UART_sendHex8(uint8_t value) void UART_sendHex16(uint16_t value) void UART_sendHex32(uint32_t value)
Check for new received data
Returns true if new data is available and false otherwise.
bool UART_available(void)
Wait for transmission complete
Waits in a while loop until all bytes in the buffer have been transmitted. Can
be used before putting the microcontroller to sleep to ensure all data has
been transmitted. Baud rate and SYSCLK are used to calculate the time it takes
for the last byte to be transmitted after the interrupt is disabled but the
last byte is still transmitted.
void UART_isSending(float sysclk, float baudrate)
Parameters
sysclk
CPU clock frequency in Hertz.
baudrate
UART baudrate used in initialization function.
Read a byte
Returns the next received byte or 0 if no new data is available. Should be
used only if UART_available() returns true.
uint8_t UART_read(void)
Read bytes
Read received bytes into the provided buffer. The function terminates if the
specified length has been read, or it times out (around 0.5s).
uint8_t UART_readBytes(uint8_t* buff, uint8_t length)
Parameters
uint8_t* buff
An array buffer where to put incoming data.
uint8_t length
Length of the array.
Return: the number of characters read.
Usage:
const uint8_t bufferSizeRX = 20; uint8_t buff[bufferSizeRX]; if(UART_available()){ // Read serial data UART_readBytes(buff, bufferSizeRX); // Now 'buff' contains received data }
Read bytes until
Read received bytes into the provided buffer. The function terminates if the specified length has been read, the termination character has been found or it times out (around 0.5s). The termination character is not included in the buffer.
uint8_t UART_readBytesUntil(char character, uint8_t* buff, uint8_t length)
Parameters
char character
The termination character. When this character is encountered, the function terminates.
uint8_t* buff
An array buffer where to put incoming data.
uint8_t length
Length of the array.
Return: the number of characters read.
Disable UART
Disable UART transmitter, receiver and interrupts.
void UART_end(void)
Flush
Resets buffers to 0.
void UART_flush(void)
Redirect received data
Redirects received data to a user defined function.
void UART_setRXhandler(void (*rx_func)(uint8_t c))
Usage:
void rxHandler(uint8_t c){ // This function is called inside the RX interrupt // and it should not take long time. // 'c' is the received byte. } UART_setRXhandler(&rxHandler);
Code example
#include "uart.h" #include "delay.h"
int main(void){ const uint8_t bufferSize = 20; char_size_t buff[bufferSize]; uint8_t bytes_read = 0; UART_init(SYSCLK, 115200); UART_sendString("I'm UART 0\r"); UART_sendString("Hi there!\r"); _delay_ms(2000); UART_sendString("Is this thing working?\r"); while(1){ if(UART_available()){ // Read serial data in the 'buff' array bytes_read = UART_readBytes(buff, bufferSize);
UART_sendString("Received ");
UART_sendInt(bytes_read); UART_sendString(" bytes\r"); if(bytes_read == bufferSize){ // Print received data to a serial terminal UART_sendBytes(buff, bytes_read); UART_send('\r'); } } // end if UART_available() } }
Download
uart v1.0 | ||
uart | Contains uart.h and uart.c | |
utils v1.0 | ||
utils | Used by sendInt() and sendFloat() | |
External Links | ||
Termite terminal | Nice serial terminal | |
Changelog | ||
v1.0 |
14, March, 2024: - released |
No comments:
Post a Comment