2.28 UART Driver

Overview

Universal Asynchronous Receiver Transmitter (UART) is a flexible serial communication module used to interface microcontrollers with other peripherals. It features a full duplex, asynchronous communication channel that can be used to implement protocols, such as RS-232 and RS-485.

Features

  • Supports Polling Mode, Interrupt mode and Interrupt mode with software buffer
  • Full or Half-Duplex Operation
  • 8-Bit or 9-Bit Data Width
  • Configurable Stop Bit Length
  • Parity, Framing and Buffer Overrun Error Detection

2.28.1 How to use the UART Driver

The UART driver generates a portable API interface. For an example of how to use the interface to write and read data, refer to this examples linked below. Click the links to view the code snippets associated with each

Instructions common for all code snippets: 2.28.5.1.1 UART Use Case Code Snippet Instructions.

2.28.2 Module Documentation

2.28.2.1 UART Driver

Universal Asynchronous Receiver Transmitter driver using dsPIC MCUs.

2.28.2.1.1 Module description

Universal Asynchronous Receiver Transmitter driver using dsPIC MCUs.

Data structures
  • struct UART_INTERFACE

    Structure containing the function pointers of UART driver.

Functions
Variables
  • const struct UART_INTERFACE UART1_Drv

    Structure object of type UART_INTERFACE with the custom name given by the user in the Melody Driver User interface. The default name e.g. UART1 can be changed by the user in the UART user interface. This allows defining a structure with application specific name using the 'Custom Name' field. Application specific name allows the API Portability.

2.28.2.1.2 Function Documentation

UART1_AutoBaudEventEnableGet()

bool UART1_AutoBaudEventEnableGet (void )

Returns enable state of the Auto-Baud feature.

Parameters:
none
Returns:

true - Auto-Baud is enabled

false - Auto-Baud is disabled

UART1_AutoBaudQuery()

bool UART1_AutoBaudQuery (void )

Returns the status of Auto-Baud detection.

Parameters:
none
Returns:

true - Auto-Baud detection in progress or counter overflow occurred

false - Auto-Baud detection is complete or disabled

UART1_AutoBaudSet()

void UART1_AutoBaudSet (bool enable)

Enables or disables UART1 Auto-Baud detection.

Parameters:
in enable

- true, starts the auto-baud detection  

in enable

- false, disables the auto-baud detection  

Returns:

none

UART1_BaudRateGet()

uint32_t UART1_BaudRateGet (void )

Gets the actual Baud-Rate of UART1.

Parameters:
none
Returns:

Actual baud-rate of UART1

UART1_BaudRateSet()

void UART1_BaudRateSet (uint32_t baudRate)

Sets the calculated Baud-Rate of UART1.

Parameters:
in baudRate

- Value of Baud-Rate to be set  

Returns:

none

Note:

Make sure the is no transmission in progress using UART1_IsTxDone function

UART1_BRGCountGet()

uint32_t UART1_BRGCountGet (void )

Gets the BRG value of UART1.

Parameters:
none
Returns:

Combined BRG value upto 20 bits

UART1_BRGCountSet()

void UART1_BRGCountSet (uint32_t brgValue)

Sets the BRG value of UART1.

Parameters:
in baudRate

- BRG value upto 20 bits  

Returns:

none

Note:

Make sure the is no transmission in progress using UART1_IsTxDone function

UART1_Deinitialize()

void UART1_Deinitialize (void )

Deinitializes the UART to POR values.

Parameters:
none
Returns:

none

UART1_ErrorGet()

size_t UART1_ErrorGet (void )

Returns the error status of UART1.

Parameters:
none
Returns:

Errors with masking as per UART1_ERROR_MASKS

UART1_FramingErrorCallback()

void UART1_FramingErrorCallback (void )

This is the default callback with weak attribute. The user can override and implement the default callback without weak attribute or can register a custom callback function using UART1_FramingErrorCallbackRegister.

Parameters:
none
Returns:

none

UART1_FramingErrorCallbackRegister()

void UART1_FramingErrorCallbackRegister (void(*)(void) handler)

This function can be used to override default callback UART1_FramingErrorCallback and to define custom callback for UART1 FramingError event.

Parameters:
UART1_Initialize()

void UART1_Initialize (void )

Initializes the UART driver.

Parameters:
none
Returns:

none

UART1_IsRxReady()

bool UART1_IsRxReady (void )

Returns a boolean value if data is available to read.

Parameters:
none
Returns:

true - Data available to read

false - Data not available to read

UART1_IsTxDone()

bool UART1_IsTxDone (void )

Indicates if all bytes have been transferred.

Parameters:
none
Returns:

true - All bytes transferred

false - Data transfer is pending

UART1_IsTxReady()

bool UART1_IsTxReady (void )

Returns a boolean value if data can be written.

Parameters:
none
Returns:

true - Data can be written

false - Data can not be written

UART1_OverrunErrorCallback()

void UART1_OverrunErrorCallback (void )

This is the default callback with weak attribute. The user can override and implement the default callback without weak attribute or can register a custom callback function using UART1_OverrunErrorCallbackRegister.

Parameters:
none
Returns:

none

UART1_OverrunErrorCallbackRegister()

void UART1_OverrunErrorCallbackRegister (void(*)(void) handler)

This function can be used to override default callback UART1_OverrunErrorCallback and to define custom callback for UART1 OverrunError event.

Parameters:
UART1_ParityErrorCallback()

void UART1_ParityErrorCallback (void )

This is the default callback with weak attribute. The user can override and implement the default callback without weak attribute or can register a custom callback function using UART1_ParityErrorCallbackRegister.

Parameters:
none
Returns:

none

UART1_ParityErrorCallbackRegister()

void UART1_ParityErrorCallbackRegister (void(*)(void) handler)

This function can be used to override default callback UART1_ParityErrorCallback and to define custom callback for UART1 ParityError event.

Parameters:
UART1_Read()

uint8_t UART1_Read (void )

Reads a byte of data from the UART1.

Precondition:

Check receive status using UART1_IsRxReady function before calling this function or call this function within the UART1_RxCompleteCallback.

Parameters:
none
Returns:

A data byte received by the driver.

UART1_RxCompleteCallback()

void UART1_RxCompleteCallback (void )

This is the default callback with weak attribute. The user can override and implement the default callback without weak attribute or can register a custom callback function using UART1_RxCompleteCallbackRegister.

Parameters:
none
Returns:

none

UART1_RxCompleteCallbackRegister()

void UART1_RxCompleteCallbackRegister (void(*)(void) handler)

This function can be used to override default callback UART1_RxCompleteCallback and to define custom callback for UART1 RxComplete event.

Parameters:
UART1_TransmitDisable()

void UART1_TransmitDisable (void )

Disables UART1 transmit.

Parameters:
none
Returns:

none

UART1_TransmitEnable()

void UART1_TransmitEnable (void )

Enables UART1 transmit.

Parameters:
none
Returns:

none

UART1_TransmitInterruptDisable()

void UART1_TransmitInterruptDisable (void )

Disables UART1 transmit interrupt.

Note:

This API is not generated in interrupt mode with a software buffer enabled or in polling mode

Do not disable the interrupt when transmission in progress

Software bufferes are not used when transmit interrupt is disabled

Parameters:
none
Returns:

none

UART1_TransmitInterruptEnable()

void UART1_TransmitInterruptEnable (void )

Enables UART1 transmit interrupt.

Note:

This API is not generated in interrupt mode with a software buffer enabled or in polling mode.

Parameters:
none
Returns:

none

UART1_TxCollisionCallback()

void UART1_TxCollisionCallback (void )

This is the default callback with weak attribute. The user can override and implement the default callback without weak attribute or can register a custom callback function using UART1_TxCollisionCallbackRegister.

Parameters:
none
Returns:

none

UART1_TxCollisionCallbackRegister()

void UART1_TxCollisionCallbackRegister (void(*)(void) handler)

This function can be used to override default callback UART1_TxCollisionCallback and to define custom callback for UART1 TxCollision event.

Parameters:
UART1_TxCompleteCallback()

void UART1_TxCompleteCallback (void )

This is the default callback with weak attribute. The user can override and implement the default callback without weak attribute or can register a custom callback function using UART1_TxCompleteCallbackRegister.

Parameters:
none
Returns:

none

Note:

This callback is triggerred if there is data in the software buffer and there is atleast one byte space in hardware transmit FIFO

UART1_TxCompleteCallbackRegister()

void UART1_TxCompleteCallbackRegister (void(*)(void) handler)

This function can be used to override default callback UART1_TxCompleteCallback and to define custom callback for UART1 TxComplete event.

Parameters:
UART1_Write()

void UART1_Write (uint8_t data)

Writes a byte of data to the UART1.

Precondition:

UART1_Initialize function should have been called before calling this function. The transfer status should be checked to see if transmitter is not full before calling this function.

Parameters:
in data

- Data byte to write to the UART1

Returns:

none

2.28.2.1.3 Variable Documentation

UART1_Drv

const struct UART_INTERFACE UART1_Drv

Structure object of type UART_INTERFACE with the custom name given by the user in the Melody Driver User interface. The default name e.g. UART1 can be changed by the user in the UART user interface. This allows defining a structure with application specific name using the 'Custom Name' field. Application specific name allows the API Portability.

2.28.3 Class Documentation

2.28.3.1 UART_INTERFACE Struct Reference

Structure containing the function pointers of UART driver.

2.28.3.1.1 Detailed Description

Structure containing the function pointers of UART driver.

#include <uart_interface.h>

Public Attributes

2.28.3.1.2 Member Data Documentation

The documentation for this struct was generated from the following file:

source/

uart_interface.h

AutoBaudQuery

bool(* AutoBaudQuery) (void)

Pointer to UARTx_AutoBaudQuery e.g. UART1_AutoBaudQuery.

AutoBaudSet

void(* AutoBaudSet) (bool enable)

Pointer to UARTx_AutoBaudSet e.g. UART1_AutoBaudSet.

BaudRateGet

uint32_t(* BaudRateGet) (void)

Pointer to UARTx_BaudRateGet e.g. UART1_BaudRateGet.

BaudRateSet

void(* BaudRateSet) (uint32_t baudRate)

Pointer to UARTx_BaudRateSet e.g. UART1_BaudRateSet.

BRGCountGet

uint32_t(* BRGCountGet) (void)

Pointer to UARTx_BRGCOuntGet e.g. UART1_BRGCountGet.

BRGCountSet

void(* BRGCountSet) (uint32_t brgValue)

Pointer to UARTx_BRGCountSet e.g. UART1_BRGCountSet.

Deinitialize

void(* Deinitialize) (void)

Pointer to UARTx_Deinitialize e.g. UART1_Deinitialize.

ErrorGet

size_t(* ErrorGet) (void)

Pointer to UARTx_ErrorGet e.g. UART1_ErrorGet.

FramingErrorCallbackRegister

void(* FramingErrorCallbackRegister) (void(*CallbackHandler)(void))

Pointer to UARTx_FramingErrorCallbackRegister e.g. UART1_FramingErrorCallbackRegister (defined only in interrupt mode)

Initialize

void(* Initialize) (void)

Pointer to UARTx_Initialize e.g. UART1_Initialize.

IsRxReady

bool(* IsRxReady) (void)

Pointer to UARTx_IsRxReady e.g. UART1_IsRxReady.

IsTxDone

bool(* IsTxDone) (void)

Pointer to UARTx_IsTxDone e.g. UART1_IsTxDone.

IsTxReady

bool(* IsTxReady) (void)

Pointer to UARTx_IsTxReady e.g. UART1_IsTxReady.

OverrunErrorCallbackRegister

void(* OverrunErrorCallbackRegister) (void(*CallbackHandler)(void))

Pointer to UARTx_OverrunErrorCallbackRegister e.g. UART1_OverrunErrorCallbackRegister (defined only in interrupt mode)

ParityErrorCallbackRegister

void(* ParityErrorCallbackRegister) (void(*CallbackHandler)(void))

Pointer to UARTx_ParityErrorCallbackRegister e.g. UART1_ParityErrorCallbackRegister (defined only in interrupt mode)

Read

uint8_t(* Read) (void)

Pointer to UARTx_Read e.g. UART1_Read.

RxCompleteCallbackRegister

void(* RxCompleteCallbackRegister) (void(*CallbackHandler)(void))

Pointer to UARTx_RxCompleteCallbackRegister e.g. UART1_RxCompleteCallbackRegister (defined only in interrupt mode)

TransmitDisable

void(* TransmitDisable) (void)

Pointer to UARTx_TransmitDisable e.g. UART1_TransmitDisable.

TransmitEnable

void(* TransmitEnable) (void)

Pointer to UARTx_TransmitEnable e.g. UART1_TransmitEnable.

TxCollisionCallbackRegister

void(* TxCollisionCallbackRegister) (void(*CallbackHandler)(void))

Pointer to UARTx_TxCollisionCallbackRegister e.g. UART1_TxCollisionCallbackRegister (defined only in interrupt mode)

TxCompleteCallbackRegister

void(* TxCompleteCallbackRegister) (void(*CallbackHandler)(void))

Pointer to UARTx_TxCompleteCallbackRegister e.g. UART1_TxCompleteCallbackRegister (defined only in interrupt mode)

Write

void(* Write) (uint8_t)

Pointer to UARTx_Write e.g. UART1_Write.

2.28.4 File Documentation

2.28.4.1 source/uart1.h File Reference

This is the generated driver header file for the UART1 driver.

#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include "uart_interface.h"

2.28.4.1.1 Functions

2.28.4.1.2 Variables

  • const struct UART_INTERFACE UART1_Drv

    Structure object of type UART_INTERFACE with the custom name given by the user in the Melody Driver User interface. The default name e.g. UART1 can be changed by the user in the UART user interface. This allows defining a structure with application specific name using the 'Custom Name' field. Application specific name allows the API Portability.

2.28.4.1.3 Detailed Description

This is the generated driver header file for the UART1 driver.

UART1 Generated Driver Header File

2.28.4.2 source/uart_interface.h File Reference

#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include "uart_types.h"

2.28.4.2.1 Data structures

  • struct UART_INTERFACE

    Structure containing the function pointers of UART driver.

2.28.4.2.2 Detailed Description

UART Generated Driver Interface Header File

2.28.4.3 source/uart_types.h File Reference

This is the generated driver types header file for the UART driver.

2.28.4.3.2 Detailed Description

This is the generated driver types header file for the UART driver.

UART Generated Driver Types Header File

2.28.4.3.3 Enumeration Type Documentation

UART_ERROR_MASKS

enum UART_ERROR_MASKS

UART_ERROR_FRAMING_MASK
UART_ERROR_PARITY_MASK
UART_ERROR_RX_OVERRUN_MASK
UART_ERROR_TX_COLLISION_MASK
UART_ERROR_AUTOBAUD_OVERFLOW_MASK

2.28.5 Module Documentation

2.28.5.1 UART Use Cases

2.28.5.1.1 UART Use Case Code Snippet Instructions

The use cases show example uses of the UART Driver, within a MCC Melody project:
  • Add UART to the project

  • Configure:
    1. The UART as described in the example.

    2. Any other peripherals or pins needed for the use case.

  • Generate the code

  • Add the code snippet(s) to the application code

  • Program the board

2.28.5.1.2 UART Use Case 1: Printf with Variable Counter

This example uses printf to print: "x Hello World!" to a terminal, where x is a counter.

  • UART:
    1. UART Dependency Selection: Select the UART connected to Serial/CDC port.

    2. Redirect STDIO to UART (for printf support): Yes

  • System > Pins, for all pins check board schematics:
    1. Pin Grid View: Select pin for UART Transmit - Tx and Receive - Rx.

After configuring the components as described above, click 'Generate' to generate the code. Then add the following code snippets to your application:

This use case prints the following to a terminal:  

0. Hello World!  

1. Hello World!  

2. Hello World!  

3. Hello World!  

4. Hello World!

#include "mcc_generated_files/system/system.h"
#include "mcc_generated_files/uart/uart1.h"
#include "mcc_generated_files/system/pins.h"
#include "string.h"

const struct UART_INTERFACE *UartSerial = &UART1_Drv;
/* Add the code snippet to the application code, e.g. main.c */
void UART_Print_Loop(uint8_t count)
{
    uint8_t index;
    for(index = 0; index < count; index++)
    {
        printf("%d. Hello World!\n",index);
    }
}
int main()
{
    SYSTEM_Initialize();
    UART_Print_Loop(5);  //Function call
    while(1)
    {
        
    }
}

2.28.5.1.3 UART Use Case 2: Write String

Write the string ‘Hello World!’ or any message, by calling UART_String_Write(msg), passing the message to print on the terminal. This can be a light-weight alternative to printf, e.g., for a string of ASCII characters.

  • UART:
    1. UART Dependency Selection: Select the UART connected to Serial/CDC port.

  • System > Pins, for all pins check board schematics:
    1. Pin Grid View: Select pin for UART Transmit - Tx and Receive - Rx.

After configuring the components as described above, click 'Generate' to generate the code. Then add the following code snippets to your application:

#include "mcc_generated_files/system/system.h"
#include "mcc_generated_files/uart/uart1.h"
#include "mcc_generated_files/system/pins.h"
#include "string.h"

const struct UART_INTERFACE *UartSerial = &UART1_Drv;
char msg[] = "Hello World!\r\n";

void UART_String_Write(const char *msg)
{
    uint8_t index;
    for(index = 0; index < strlen(msg); index++)
    {
        while(!UartSerial->IsTxReady());
        UartSerial->Write(msg[index]);
    }
}
int main()
{
    SYSTEM_Initialize();
    UART_String_Write(msg);  //Function Call
    while(1)
    {
        
    }
}

2.28.5.1.4 UART Use Case 3: Control Commands - Using Interrupt Mode

This example shows how to implement a basic Command Line Interface (CLI) using Interrupt Mode, a popular way of sending control commands to the microcontroller over the UART. LED is controlled using commands from a terminal, e.g., on the MPLAB Data Visualizer.

  • UART:
    1. UART Dependency Selection: Select the UART connected to Serial/CDC port.

    2. Redirect STDIO to UART (for printf support): Yes

    3. Interrupt Driven Mode : Enable

  • System > Pins, for all pins check board schematics:
    1. Pin Grid View: Select pin for UART Transmit - Tx and Receive - Rx.

    2. Pin Grid View: Select LED pin as output.  

    3. Pins: Rename Custom Name to "LED".  

After configuring the components as described above, click 'Generate' to generate the code. Then add the following code snippets to your application:

  • Control LED using terminal commands. The commands are case sensitive.
    1. Send "ON" to turn the LED.

    2. Send "OFF" to turn it off.

#include "mcc_generated_files/system/system.h"
#include "mcc_generated_files/uart/uart1.h"
#include "string.h"
#include "mcc_generated_files/system/pins.h"

#define MAX_COMMAND_LEN 8

const struct UART_INTERFACE *UartSerial = &UART1_Drv;

enum SERIAL_COMMAND
{
    SERIAL_COMMAND_ON = 0,
    SERIAL_COMMAND_OFF,
    SERIAL_COMMAND_INVALID,
    SERIAL_COMMAND_MAX
};

bool serial_mutex = false;

uint8_t command[MAX_COMMAND_LEN];
uint8_t index_count = 0;
uint8_t read_msg;
uint8_t led_status;
void UART_ExecuteCommand(uint8_t *command)
{
    if(strcmp(command, "ON") == 0)
    {
        LED_SetHigh();
        led_status = SERIAL_COMMAND_ON;
    }
    else if (strcmp(command, "OFF") == 0)
    {
        LED_SetLow();
        led_status = SERIAL_COMMAND_OFF;
    }
    else
    {
        led_status = SERIAL_COMMAND_INVALID;
    }
}
void UART_ProcessCommand_Callback(void)
{ 
      if(UartSerial->IsRxReady())
      {
        read_msg = UartSerial->Read();
        if(read_msg != '\n' && read_msg != '\r')
        {
            command[index_count++] = read_msg;
            if((index_count) > MAX_COMMAND_LEN)
            {
                (index_count) = 0;
            }
        }
        if(read_msg == '\n')
        {
            command[index_count] = '\0';
            index_count = 0;
            UART_ExecuteCommand(command);
            serial_mutex = true;
        }
      }   
}
int main(void)
{
    SYSTEM_Initialize();    
      
    UartSerial->RxCompleteCallbackRegister(&UART_ProcessCommand_Callback);  //Receiver Complete Callback registry
   
    printf("In the terminal, send 'ON' to turn the LED on, and 'OFF' to turn it off.\r\n");
    printf("Note: commands 'ON' and 'OFF' are case sensitive.\r\n");
    
    while(1)
    {        
       if(serial_mutex)
       {
           switch(led_status)
           {
               case SERIAL_COMMAND_ON:
                   printf("OK, LED ON.\r\n");
                   break;
                  
               case SERIAL_COMMAND_OFF:
                   printf("OK, LED OFF.\r\n");
                   break;
                   
               case SERIAL_COMMAND_INVALID:
                   printf("Incorrect command.\r\n");
                   break;
                   
               default:
                   break;
           }
           
           serial_mutex = false;   
       }
    }
}

2.28.5.1.5 UART Use Case 4: Control Commands - Using Polling Mode

This is a continuation of UART Use Case 3 but this time in Polling Mode. Instead of registering interrupt callback for UART_ProcessCommand_Callback, we just modify the main.c as per below given code snippet. Copy the UART_ExecuteCommand, Global variables and defines from the above UART Use Case 3.

  • UART:
    1. UART Dependency Selection: Select the UART connected to Serial/CDC port.

    2. Redirect STDIO to UART (for printf support): Yes

    3. Interrupt Driven Mode : Disabled

  • System > Pins, for all pins check board schematics:
    1. Pin Grid View: Select pin for UART Transmit - Tx and Receive - Rx.

    2. Pin Grid View: Select LED pin as output.  

    3. Pins: Rename Custom Name to "LED".  

After configuring the components as described above, click 'Generate' to generate the code. Then add the following code snippets to your application:

  • Control LED using terminal commands. The commands are case sensitive.
    1. Send "ON" to turn the LED.

    2. Send "OFF" to turn it off.

int main(void)
{
    SYSTEM_Initialize();    
 
    printf("In the terminal, send 'ON' to turn the LED on, and 'OFF' to turn it off.\r\n");
    printf("Note: commands 'ON' and 'OFF' are case sensitive.\r\n");
    
    while(1)
    {     
        UART_ProcessCommand_Callback();
        
        if(serial_mutex)
        {
            switch(led_status)
            {
                case SERIAL_COMMAND_ON:
                    printf("OK, LED ON.\r\n");
                    break;

                case SERIAL_COMMAND_OFF:
                    printf("OK, LED OFF.\r\n");
                    break;

                case SERIAL_COMMAND_INVALID:
                    printf("Incorrect command.\r\n");
                    break;

                default:
                    break;
            }
            serial_mutex = false;   
        }
    }
}

2.28.5.1.6 UART Use Case 5: Mirror Back Typed Characters

 

This example demonstrates how to send and receive data byte using UART read and write functions. A catch for a read error, if any, in the received byte is also implemented.

  • UART:
    1. UART Dependency Selection: Select the UART connected to Serial/CDC port.

    2. Redirect STDIO to UART (for printf support): Yes

  • System > Pins, for all pins check board schematics:
    1. Pin Grid View: Select pin for UART Transmit - Tx and Receive - Rx.

    2. Pins : Transmit pin should be selected as Start High

After configuring the components as described above, click 'Generate' to generate the code. Then add the following code snippets to your application:

#include "mcc_generated_files/system/system.h"
#include "mcc_generated_files/uart/uart1.h"
#include "mcc_generated_files/system/pins.h"
#include "string.h"

const struct UART_INTERFACE *UartSerial = &UART1_Drv; 
/* Echoes back any characters types into terminal. */
void UART_EchoCharacters(void)
{
    if(UART_Serial.IsRxReady())
    {
         uint8_t serialCOMRxdByte = 0;
    
        serialCOMRxdByte = UART_Serial.Read();
        size_t stat = UART_Serial.ErrorGet();  
        if((stat == UART_ERROR_TX_COLLISION_MASK) ^ (stat != 0))   
        {
            printf("Error %x\r\n",stat);
        }
        if(UART_Serial.IsTxReady())
        {
            UART_Serial.Write(serialCOMRxdByte);
        }
    }    
}
int main(void)
{
    SYSTEM_Initialize();
    printf("Hello World!\r\n");
    printf("Type characters in the terminal, to have them echoed back ...\r\n");
    
    while(1)
    {
        UART_EchoCharacters();  //Function call
    }   
}