A highly customizable UART library that can also be called USART since it has the option for synchronous transfer mode. It can work with transmit and receive buffers down to 1 byte in size, making it suitable for devices with small memory. It was mainly made for ATmega328PB.
AVR microcontrollers have support for both UART and USART modes. USART stands for Universal Synchronous Asynchronous Receiver Transmitter. Notice that UART lacks the S that stands for Synchronous.
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.
Features
- Custom Baud rate
- Asynchronous or synchronous modes
- Supports serial frames with 5, 6, 7, 8, or 9 data bits
- Odd, even or no parity
- Error detection
- Multi-processor communication mode used to address multiple devices on the same serial bus
- Double speed asynchronous communication mode
Contents
USART Characteristics
USART can be set to work in the following modes: Normal asynchronous, Double Speed asynchronous, Master synchronous, Slave synchronous mode and Multi-Processor Communication Mode.
Asynchronous and synchronous serial
Asynchronous means that data is transferred without support from an external clock signal since the clock is generated internally and is synchronized to the incoming serial frames.
Synchronous mode requires an extra clock line but has the advantage that it can work at higher speed rates that is asynchronous mode.
In Master synchronous the the main device generates and outputs the clock on XCKn pin while in Slave synchronous mode the device uses the clock generated by the Master.
Multi-Processor Communication Mode
The Multi-Processor Communication mode enables several slave MCUs to receive data from a master MCU. This is done by first decoding an address frame to find out which MCU has been addressed. If a particular slave MCU has been addressed, it will receive the following data frames as normal, while the other slave MCUs will ignore the received frames until another address frame is received.
Frame formats
A serial frame is composed of a character of data bits with synchronization bits (start and stop bits), and optionally a parity bit for error checking.
A frame starts with the start bit, followed by the data bits (from 5 up to 9 data bits in total): first the least significant data bit, then the next data bits ending with the most significant bit. If enabled, the parity bit is inserted after the data bits, before the one or two stop bits. 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 possible combinations of the frame formats. Bits inside brackets are optional.
IDLE: No transfers on the communication line (Rx or Tx). An IDLE line
must be high.
St: Start bit, always low.
(n): Data bits (0 to 8).
P: Parity bit. Can be odd or even.
Sp: 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.
Wiring
Some AVRs have two UARTs with pins named RXDn (Receiver) and TXDn (Transmitter). n represent the UART number - 0 or 1.
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.
In Synchronous mode you also need the XCKn pin for clock.
For ATmega328PB the TX/RX pins are as follows:
TXD0 - PD1, RXD0 - PD0, XCK0 - PD4
TXD1 - PB3, RXD1 - PB4, XCK1 - PB5
For other types of microcontroller check the Pin Configurations chapter
of the datasheet.
Using UART library
Selecting UART number
By default, the library is set to use UART0. To use UART1 set UART_NUMBER to 1.
#define UART_NUMBER 0
TX and RX buffers
Transmitted and Received data are buffered in two circular arrays that by default have a size of 64 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 to the microcontroller to process that data.
#define UART_TX_BUFFER_SIZE 64 #define UART_RX_BUFFER_SIZE 64
Initialization function
Sets the baud rate, frame format, enables UART interrupts and global interrupts. The function can be used at any point to change baud rate or frame parameters.
void UART_begin()
Parameters
uint32_t baudrate
Bits per second
uint8_t mode
UART mode: Asynchronous Normal mode, Asynchronous Double Speed, Synchronous Master/Slave mode. When using synchronous mode, the Data Direction Register for the XCKn pin controls whether the clock source is internal (Master mode) or external (Slave mode). The XCKn pin is only active when using synchronous mode.
Available constants: UART_ASYNC_NORMAL, UART_ASYNC_DOUBLE_SPEED, UART_SYNC.
uint8_t parity
UART_NO_PARITY, UART_EVEN_PARITY, UART_ODD_PARITY
uint8_t bits
Number of bits in the frame, from 5 to 8. Most common format is having 8 bits but if you have small numbers and speed is important, using 5, 6 or 7 bits can provide a bit more speed. The maximum number that can be transmitted is 2^n where n is the number of bits. 9 bits is usually only used in Multi-processor Communication mode where the 9'th bit indicate an address or data frame.
UART_5_BIT, UART_6_BIT, UART_7_BIT, UART_8_BIT.
Send a byte
Puts a byte of data in the transmit buffer and enables the Data Register Empty Interrupt.
void UART_send()
Parameters
uint8_t data
The data byte
Send a string
Send a null terminated string.
void UART_sendString()
Parameters
char* s
A string
Send bytes
Send a series of bytes in a buffer.
void UART_sendBytes()
Parameters
uint8_t* buff
An array of bytes.
uint8_t length
Length of the array.
Send an integer number
Convert an integer number into a string array and send it over UART.
void UART_sendInt()
Parameters
INT_SIZE number
INT_SIZE is defined in the "utils.h" and can be int32_t or int64_t
Send a float number
Convert a float number into a string array and send it over UART.
void UART_sendFloat()
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 data
Returns true if new data is available.
bool UART_available(void)
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()
Parameters
uint8_t* buff
An array buffer where to put incomming data.
uint8_t length
Length of the array.
Return
Returns the number of characters read.
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()
Parameters
char character
The termination character. When this character is encountered, the function terminates.
uint8_t* buff
An array buffer where to put incomming data.
uint8_t length
Length of the array.
Return
Returns the number of characters read.
Disable UART
Disable UART transmitter, receiver and interrupts.
void UART_end(void)
Flush
If the UART buffer has to be flushed during normal operation, due to for
instance an error condition, read the UDRn I/O location until the RXCn Flag is
cleared.
void USART_flush(void)
Receiver error flags
After each byte is received, the error bits in the UART register are saved in
a global variable. The following macros can be used to check if an error
occurred and the type of error.At the end, the error flag must be cleared.
if(UART_error()){ if(UART_frameError()){ UART_sendString("Frame Error\r"); } if(UART_parityError()){ UART_sendString("Parity Error\r"); } if(UART_dataOverRunError()){ UART_sendString("Data OverRun\r"); } UART_clearErrorFlag(); }
Frame Error
The Frame Error (FE) Flag indicates the state of the first stop bit of the next readable frame stored in the receive buffer. The FE Flag is zero when the stop bit was correctly read as '1', and the FE Flag will be one when the stop bit was incorrect (zero). This flag can be used for detecting out-of-sync conditions, detecting break conditions and protocol handling.
Parity Error
The Parity Error (UPE) Flag indicates that the next frame in the receive
buffer had a Parity Error when received. If Parity Check is not enabled the
UPE bit will always read '0'.
Data OverRun
The Data OverRun (DOR) Flag indicates data loss due to a receiver buffer full
condition. A Data OverRun occurs when the receive buffer is full (two
characters), a new character is waiting in the Receive Shift Register, and a
new start bit is detected. If the DOR Flag is set, one or more serial frames
were lost between the last frame read from UDR, and the next frame read from
UDR.
Enable MPCM
Enable the Multi-processor Communication mode (MPCM). After this function sets
the MPCM bit, frames that do not contain an address will be ignored by the
UART. Frames containing an address have the 9'th bit set to 1.
void UART_mpcmEnable(void)
Disable MPCM
Disables the Multi-processor Communication mode (MPCM). After this function
sets the MPCM bit to 0, data frames can be received. This should be used after
a valid address has been received after using UART_mpcmEnable().
void UART_mpcmDisable(void)
Send UART address
Select a device by sending an address frame over UART.
void UART_mpcmSelectDevice()
Parameters
uint8_t address
Address of the device to select.
Code example
#define F_CPU 16000000 #include <avr/io.h> #include <util/delay.h> #include "uart.h" int main(void){ const uint8_t bufferSize = 20; uint8_t buff[bufferSize]; uint8_t bytes_read = 0; UART_begin(9600, UART_ASYNC_NORMAL, UART_EVEN_PARITY, UART_8_BIT); UART_sendString("Hi there!\r"); _delay_ms(5000); UART_sendString("Is this thing working?\r"); while(1){ if(UART_available()){ // Read serial data bytes_read = UART_readBytes(buff, bufferSize); UART_sendInt(bytes_read); UART_send('\r'); if(bytes_read){ // Print received data to a serial terminal UART_sendBytes(buff, bytes_read); UART_send('\r'); } // Check for transmission errors if(UART_error()){ if(UART_frameError()){ UART_sendString("Frame Error\r"); } if(UART_parityError()){ UART_sendString("Parity Error\r"); } if(UART_dataOverRunError()){ UART_sendString("Data OverRun\r"); } UART_clearErrorFlag(); } } } }
Download
Version 1.0
utils.h - used to convert numbers into strings.
Share it if you like it!
No comments:
Post a Comment