WebbotLib AVR library
WebbotLib It just does it
  C++ documentation  C documentation

uart.h

Routines for handling serial communications with other devices by using built-in UART hardware.
If you run out of UARTs you can use uartsw.h instead to simulate a UART in code. Obviously software simulation cannot cope with very high baud rates and this will depend on the clock speed of your processor, the required baud rate, and how 'busy' your micro-controller is.
The UARTs are not automatically initialised at start up and so you must initialise them by hand. The serial motor drivers will do this for you but when using rprintf debug commands over a UART then you must use uartInit(UART* uart, BAUD_RATE baud) in your initialisation code to set up the baud rate. Older versions of the library used to do this for you but has been removed mainly because it could cause random characters to be output to the UART due to power switch contact bounce.
By default the UARTs have no transmit and receive buffers. This means that when you try to transmit a byte then your program will pause until any previous byte has been sent. Received characters will be thrown away unless you use uartAttach to attach a callback routine that is called when the character is received.
Alternatively you can supply transmit and receive buffers by specifying UART_RX_BUFFER_SIZE and/or UART_TX_BUFFER_SIZE at the top of your program file (before you include the system file). If you specify a transmit buffer size then all transmissions will occur in the background and your program will not pause unless the transmit buffer fills up because you are adding characters faster than they can be sent. If you specify a receive buffer then all received data is queued up until you read it. If you fail to read the received data frequently enough then the receive buffer may overflow and characters will be lost.
To set up the UARTs with a transmit buffer of 80 bytes and a receive buffer of 20 bytes then you would add the following lines to the very top of your program:-
#define UART_TX_BUFFER_SIZE 80
#define UART_RX_BUFFER_SIZE 20
Most of the functions in this module require a reference to the UART you want to perform the action upon. Each uart has a name such as UART0, UART1 etc. Alternatively, you can iterate through all of the available hardware uarts as follows:-
int i;
for(i=0;i<NUM_UARTS;i++){
HW_UART* theUart = &Uarts[i];
// You can now pass in 'theUart' as the reference
}

 

Function

 


int uartGetByte(UART* uart)

Returns the next byte from the receive buffer or -1 if there is no buffer or the buffer is empty.
Example:
int ch = uartGetByte(UART0);
if(ch!=-1){
// We have got a character in 'ch'
}
There are shorthand forms when dealing with a specific uart. eg
uart0GetByte() is the same thing as uartGetByte(UART0) and
uart1GetByte() is the same thing as uartGetByte(UART1)
The shorthand forms do exactly the same thing but because they don't need to pass a parameter then they result in smaller code. However: they make it harder if you suddenly decide to change your code to receive via a different UART as you will have to search and replace all the shorthand forms. The longer form allows you to use a #define at the start of your program such as:
#define LISTEN UART0
then your code can pass 'LISTEN' to all of the UART commands. Changing to another uart just involves changing the 'LISTEN' line to use another uart.

uint8_t uartSendByte(UART* uart, uint8_t txData)

Transmit a byte on the specified UART.
If the UART has a transmit buffer then the byte will be added to the buffer and sent in the background. If the buffer is full then it will pause until there is available space in the buffer.
If the UART does not have a buffer then it will pause until any previous byte has been sent and then it will transmit this byte.
For example:
uartSendByte(UART0, 'A'); // send an A character
There are shorthand forms when dealing with a specific uart. eg
uart0SendByte(data) is the same thing as uartSendByte(UART0,data) and
uart1SendByte(data) is the same thing as uartSendByte(UART1,data) etc
The shorthand forms do exactly the same thing but because they don't need to pass a parameter then they result in smaller code. However: they make it harder if you suddenly decide to change your code to transmit via a different UART as you will have to search and replace all the shorthand forms. The longer form allows you to use a #define at the start of your program such as:
#define SEND UART0
then your code can pass 'SEND' to all of the UART commands. Changing to another uart just involves changing the 'SEND' line to use another uart.
The return value is the byte you have sent and this makes it easier to do things like build checksums for the bytes that are sent.

uartSetBaudRate(UART* uart, BAUD_RATE baudrate)

Set the baud rate for the UART.
For example:
uartSetBaudRate(UART0, (BAUD_RATE)19200);
There is a 'magic' value for the baud rate called BAUD_RATE_MAX which will use the highest possible baud rate. This is equivalent to setting the baud rate divisors to 1. The actual baud rate achieved will depened on the your clock speed.

uartAttach(UART* uart, void (*rx_func)(unsigned char c, void* data))

Attaches a callback routine that is invoked, under interrupts, when a character is received rather than adding it to any receive buffer.
For example you could have your own routine:
void myReceive(unsigned char data, void* device){
// You have just received a byte in the 'data' parameter
}
You can now ask the UART0 to call it when a byte is received by writing:-
uartAttach(UART0, &myReceive, null);
Note the '&' character at the start of your function name.
Only one callback routine can be registered with a given uart at any one time.
So far we haven't mentioned the device parameter. This allows you to specify a pointer to something when you call uartAttach. This pointer is then passed on to the attached code when a character is received.
Consider the example given above - if we also attached 'myReceive' to UART1 then when 'myReceive' is called you don't know which uart the character was received by. So we can use the extra parameter to help ie:
void myReceive(unsigned char data, void* device){
    if(device == UART0){
     // You have just received a byte from UART0
    }else if(device == UART1){
        // You have just received a byte from UART1
}
}
// Point both UARTs to the same code above and use the 3rd parameter to pass
// which UART it has been called by
uartAttach(UART0, &myReceive, UART0);
uartAttach(UART1, &myReceive, UART1);

uartDetach(UART* uart)

Removes any existing receive callback from the UART.

uartFlushReceiveBuffer(UART* uart)

Discards any data in the receive buffer.
This is useful if you have changed the baud rate from some earlier value and so any characters in the receive buffer may have been received incorrectly:-
uartSetBaudRate(UART0, (BAUD_RATE)19200);
uartFlushReceiveBuffer(UART0);

cBuffer* uartGetRxBuffer(const UART* uart)

Returns the receive buffer or null if there is no buffer.

cBuffer* uartGetTxBuffer(const UART* uart)

Returns the UARTs transmit buffer or null if there is none.

boolean uartHasOverflowed(const UART* uart)

Test if the receive buffer has overflowed.
Returns TRUE if it has overflowed, ie at least one character has been lost, or FALSE if not.
The receive buffer overflows when it is receiving characters faster than you are processing them. If you are receiving bursts of data then increase the size of the receive buffer. However: if you are receiving a constant stream of data then you either need to speed up your program to cope with the data or you need to reduce the baud rate.

boolean uartReceiveBufferIsEmpty(const UART* uart)

Tests if the receive buffer is empty.
Return TRUE if it is empty (or there is no receive buffer), or FALSE if it contains at least one byte.
if(uartReceiveBufferIsEmpty(UART0)){
// We have no data to process. So do other things....
}else{
// We have data to process so start reading it in
}

uartSetReceiveBuffer(UART* uart, cBuffer* buffer)

Changes the receive buffer.
The only time you may want to use this is if you have multiple UARTs and you want them to have different receive buffer sizes. If this is what you want to do then don't define 'UART_RX_BUFFER_SIZE' at the start of your program so that the UARTs don't have a receive buffer. Then initialise them by hand in your start up code:-
unsigned char myRxBuf[128];
cBuffer myRxBuffer = MAKE_BUFFER(myRxBuf);
uartSetReceiveBuffer(UART0,&myRxBuffer);

uartSetTransmitBuffer(UART* uart, cBuffer * buffer)

Changes the transmit buffer.
The only time you may want to use this is if you have multiple UARTs and you want them to have different transmit buffer sizes. If this is what you want to do then don't define 'UART_TX_BUFFER_SIZE' at the start of your program so that the UARTs don't have a transmit buffer. Then initialise them by hand in your start up code:-
unsigned char myTxBuf[128];
cBuffer myTxBuffer = MAKE_BUFFER(myTxBuf);
uartSetTransmitBuffer(UART0,&myTxBuffer);

boolean uartIsBusy(UART* uart)

Returns FALSE if the UART has nothing left to send.
If your main loop is continually sending data over the UART, even if you have a transmit buffer, then the buffer can quickly become full since the UART is running slower than your program. Further transmissions will cause your program to halt until there is space left in the transmit buffer. Sometimes this is not what you want to do - perhaps you want your program to go at full speed and only send data when it's not going to slow down the program. That's when you need this function! Example:
if(!uartIsBusy(UART0)){
    // UART has nothing to do
    // so send your stuff out now
}
Obviously if the UART has no transmit buffer and you are sending more than 1 byte, or the message length is longer than your transmit buffer size, then there will still be a pause whilst sending the message.

uartInit(UART* uart, BAUD_RATE baud)

Re-initialise a UART after it has been turned off.

uartOff(UART* uart)

Disables the given UART once all pending transmissions have finished.

void uartSendBuffer(UART* uart, const uint8_t* data, size_t count)

Send a block of bytes to the UART.
Parameter 1 is the UART.
Parameter 2 is the address of the data to be sent.
Parameter 3 is the number of bytes to be sent starting at the address in parameter 2.
Example:-
uint8_t data[4];
data[0] = 0x55;
data[1] = 0x99;
data[2] = 'A';
data [3] = '\n';
uartSendBuffer(UART1, data, 4);

Reader uartGetReader(const UART*)

Returns the Reader associated with this UART.
A 'Reader' is a routine that can be called to get the next received character or -1 if there isn't one. The default behaviour, for a hardware UART, is to return the address of 'uartXGetByte' where 'X' is the UART number.
This has been done to make it easier to move from one UART to another. Previously you probably used a #define to identify the UART you used to connect to your PC. ie
#define PC_UART UART1
You then probably used calls to uart1GetByte to read incoming characters. This made it difficult to change to another UART as you then had to change multiple lines.
So the new way of doing this is to keep your #define for the UART and then change your read code to:
int ch = uartGetReader(PC_UART)();

Writer uartGetWriter(const UART*)

Returns the Writer for a given UART.
A 'Writer' is a routine that can be called to send a character to the UART. The default behaviour, for a hardware UART, is to return the address of 'uartXSendByte' where 'X' is the UART number.
This has been done to make it easier to move from one UART to another. Previously you probably used a #define to identify the UART you used to connect to your PC. ie
#define PC_UART UART1
You then probably used calls to uart1SendByte to write characters or you may have used rprintfInit(&uart1SendByte) to send rprintf output to the UART. This made it difficult to change to another UART as you then had to change multiple lines.
So the new way of doing this is to keep your #define for the UART and then change your write code to:
rprintfInit(uartGetWriter(PC_UART));
If you were to change the #define to use a different UART then the rprintfInit would automatically now use the correct routine to put characters to the new UART.

void uartReceivePollingMode(const HW_UART* uart,boolean polling)

Changes a hardware UART receive mode between interrupt driven and polling modes.
UARTs normally work in interrupt driven mode and potentially have a receive queue to store all the received characters. However: when using half duplex mode you only expect to receive data after you have sent something ie you 'talk' then 'listen'. When running at very high baud rates (eg 1,000,000 baud) then the processing overhead of the interrupt handling plus the queue handling can be slow enough for you to loose incoming data. Hardware interrupts for other devices only make the problem worse.
In this scenario it is better to put the receiver into 'polling' mode and then poll the UART for each incoming byte. It may even be necessary to bracket the code with a CRITICAL_SECTION_START/END so that no other interrupts cause data to be lost. But you will definitely need to make sure that you have some kind of timeout just in case you don't receive a response as this would cause everything to 'die'.
This seems like a 'dangerous' thing to do but don't forget that we are doing it because the data rate is so high. Therefore the time it takes to receive the data is actually very short.
If you want to use this in your own code then here is a half duplex example for UART0 which expects a 10 byte response:
// Put uart into polling mode for receive
uartReceivePollingMode(UART0, TRUE);
 
// Assume we have sent out some data to start with
uint8_t reply[10];   // Put the reply here
uint8_t replyPos=0;  // Nothing received yet
 
int now = 0; // Create a variable to test for timeouts
boolean timeOut = FALSE; // We haven't timed out
 
// Wait till transmit has finished
while(uartIsBusy(UART0)){
    breathe();
}
 
CRITICAL_SECTION_START; // Turn off hardware interrupts
while(replyPos < sizeof(reply)){
    int ch = uartPollByte(UART0);
    if(ch != -1){
        reply[replyPos++] = (uint8_t)(ch & 0xff);
        now = 0; // Reset the timeout counter
    }else if(--now == 0){  // Timeout after a while
        timeOut = TRUE;
        break;
    }
}
CRITICAL_SECTION_END; // Turn interrupts back on

int uartPollByte(const HW_UART* uart)

Poll the hardware UART to see if a byte has been received.
Returns the byte or -1 if nothing has been received yet.

Valid XHTML 1.0 Transitional