3.5 UART Driver

3.5.1 Introduction

The MCC Melody UART Driver generates a portable API interface to support a generic UART interface supporting the MCC Melody Component concepts both Configuration and Firmware portability.

The UART Driver will require a PLIB dependency (Peripheral LIBrary), closely associated to a UART (Universal Asynchronous serial Receiver and Transmitte) hardware peripheral. On AVR MCUs the peripheral is sometimes called USART (Universal Synchronous Asynchronous Receiver Transmitter) to emphasize enhanced functionalities.

The UART is very often used for terminal communications, e.g. via the Curiosity Nano's on-board debugger.

3.5.2 Required header files:

#include"mcc_generated_files/uart/usart[X].h"
Note: Replace [X] with the instance number of the selected USART module.

3.5.3 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: 3.5.4.1.1 UART Use Case Code Snippet Instructions.

Table 3-45. Running the UART Use Cases
Videos Running MCC Melody use case code snippets for AVR:
Many of use cases build on the following components, so this is a good place to start if you are new to MCC Melody:
Videos Running the MCC Melody use case code snippets for PIC16F/18F:
Many of use cases build on the following components, so this is a good place to start if you are new to MCC Melody:

3.5.4 Module Documentation

3.5.4.1 UART Use Cases

3.5.4.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

3.5.4.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.

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" 
/* Add the code snippet to the application code, e.g. main.c */
void UART_print_loop(uint8_t count)
{
    int i;
    for(i = 0; i < count; i++)
    {
        printf("%d. Hello World!\n",i);
    }
}
UART_print_loop(5); 

3.5.4.1.3 UART Use Case 2: Write String

Write the string ‘Hello World!’ or any message, by calling UART_write_string(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.

    2. UART: UARTx renamed to UART (Custom name field)

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

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 <string.h>
char msg[] = "Hello World!\r\n";
void UART_write_string(const char *msg)
{
    for(uint8_t i = 0; i < strlen(msg); i++)
    {
        while(!UART.IsTxReady());
        UART.Write(msg[i]);
    }
}
UART_write_string(msg);

3.5.4.1.4 UART Use Case 3: Control Commands

This example shows how to implement a basic Command Line Interface (CLI), 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. UART: UARTx renamed to UART (Custom name field)

    3. 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.

    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 <string.h>

#define MAX_COMMAND_LEN 8
void UART_executeCommand(char *command)
{
    if(strcmp(command, "ON") == 0)
    {
        LED_SetLow();
        printf("OK, LED ON.\r\n");
    }
    else if (strcmp(command, "OFF") == 0)
    {
        LED_SetHigh();
        printf("OK, LED OFF.\r\n");
    }
    else
    {
        printf("Incorrect command.\r\n");
    }
}
int main(void)
{
    SYSTEM_Initialize();    
    
    char command[MAX_COMMAND_LEN];
    uint8_t index = 0;
    char c;
    
    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)
    {        
        while(!UART.IsRxReady());
        c = UART.Read();
        if(c != '\n' && c != '\r')
        {
            command[index++] = c;
            if((index) > MAX_COMMAND_LEN)
        {
            (index) = 0;
            }
        }
        if(c == '\n')
        {
            command[index] = '\0';
            index = 0;
            UART_executeCommand(command);
        }
    }
}

3.5.4.1.5 UART Use Case 4: 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. UARTx renamed to UART (Custom name field)

    3. 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.

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

  • Code modifications: usartx_status_t -> replace with reference to PLIB used. Find this by searching for "status" in uartx.c (for PIC) or usartx.c (for AVR)

#include "mcc_generated_files/system/system.h"
/* Echoes back any characters types into terminal. */
void UART_echoCharacters(void)
{
    if(UART.IsRxReady())
    {
        uint8_t serialCOMRxdByte = 0;
        
        // replace with plib used 
        usart0_status_t serialCOMStatus;

        serialCOMStatus.status = UART_ErrorGet();
        serialCOMRxdByte = UART.Read();
        if(serialCOMStatus.status)
        {
            printf("serialCOMStatus.status: 0x%X", serialCOMStatus.status);
        }
        if(UART.IsTxReady())
        {
            UART.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();
    }
}

3.5.5 Class Documentation

3.5.5.1 UART_INTERFACE Struct Reference

3.5.5.1.1 Detailed Description

uart_interface Generated Driver API Header File

@Company Microchip Technology Inc.

@File Name uart_interface.h

@Summary This is the generated driver interface header file for the uart_interface driver.

@Description This file provides common enumerations for uart_interface driver. Generation Information : Product Revision : CCL - 1.8.2 Device : PIC18F47Q43 Driver Version : 1.0.0 The generated drivers are tested against the following: Compiler : XC8 v2.2 MPLAB : StandaloneSection: Included Filesuart_interface

@Description Structure containing the function pointers of uart_interface driver.

#include <uart_interface.h>

Public Attributes

3.5.5.1.2 Member Data Documentation

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

source/

uart_interface.h

ChecksumErrorCallbackRegister

void(* UART_INTERFACE::ChecksumErrorCallbackRegister) (void(*CallbackHandler))

ErrorCallbackRegister

void(* UART_INTERFACE::ErrorCallbackRegister) (void(*CallbackHandler)(void))

FramingErrorCallbackRegister

void(* UART_INTERFACE::FramingErrorCallbackRegister) (void(*CallbackHandler)(void))

Initialize

void(* UART_INTERFACE::Initialize) (void)

IsRxReady

bool(* UART_INTERFACE::IsRxReady) (void)

IsTxDone

bool(* UART_INTERFACE::IsTxDone) (void)

IsTxReady

bool(* UART_INTERFACE::IsTxReady) (void)

OverrunErrorCallbackRegister

void(* UART_INTERFACE::OverrunErrorCallbackRegister) (void(*CallbackHandler)(void))

ParityErrorCallbackRegister

void(* UART_INTERFACE::ParityErrorCallbackRegister) (void(*CallbackHandler))

Read

uint8_t(* UART_INTERFACE::Read) (void)

RxCompleteCallbackRegister

void(* UART_INTERFACE::RxCompleteCallbackRegister) (void(*CallbackHandler)(void))

TxCompleteCallbackRegister

void(* UART_INTERFACE::TxCompleteCallbackRegister) (void(*CallbackHandler)(void))

Write

void(* UART_INTERFACE::Write) (uint8_t)

3.5.6 File Documentation

3.5.6.1 source/uart.dox File Reference

3.5.6.2 source/uart_interface.h File Reference

#include <stdbool.h>
#include <stdint.h>
#include <xc.h>