Setting Up UART in nRF52xx

Prerequisites

This is tutorial is not intended to be a guide for learning C language or about the Nordic SDK platform. It’s primary target is to provide developers a concise guide about integrating peripheral modules and features into active applications.

If you are a beginner, I would recommend you look into an nRF52 Project Setup guide like this one.

https://medium.com/vicara-hardware-university/nrf52-project-setup-with-segger-embedded-system-f64958052a2d

Another easy way to get started with coding, without bothering with all basic stuff like files and driver inclusion, check out this Code Generation Tool

nrf52 Code Generator: https://vicara.co/nrf52-code-generator

UART

Universal Asynchronous Receiver Transmitter (UART) is a communication protocol which as the name suggests, can communicate in an asynchronous fashion, ie. without the need of a synchronizing clock.

UART is usually used in applications, where high data rates and immediate data availability are not necessary for an application. It is mostly seen in devices which require inputs from user, or in general from devices which do not have a periodic sequence of data transmission. Examples include Keyboard, Mouse or any USB device.

Fig.2 UART Operational Structure

Implementing UART in nRF52832

In the following section, I will provide a guide as it has been tested in the nRF52832 Dev Kit. However, the same structure will remain common across all nRF52 devices.

Including correct Headers

Fig.3 Project Explorer in SES

Include the UART Driver files. This file should be titled, nrf_drv_uart.c It should be available at SDK/integration/nrfx/legacy folder.

Update sdk_config.h File

  • UART_ENABLED has to be enabled.

Fig.4 UART Enable in sdk_config.h

In main.c File

Define UART Instance

staticnrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(0);

Note: nRF52832 has only 1 UART instance

UART Callback Function

staticvoiduart_event_handler(nrf_drv_uart_event_t * p_event, void* p_context)
{
if (p_event->type == NRF_DRV_UART_EVT_RX_DONE)
   {
if (p_event->data.rxtx.bytes)
       {// Event to notify that data has been received

       }
   }
elseif (p_event->type == NRF_DRV_UART_EVT_ERROR)
   {// Event to notify that an error has occured in the UART peripheral

   }
elseif (p_event->type == NRF_DRV_UART_EVT_TX_DONE)
   {// Event to notify that the last byte from FIFO has been transmitted


   }
}

Initialize UART Function

staticvoiduart_init()
{
nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;
   uart_config.baudrate = UART_BAUDRATE_BAUDRATE_Baud115200; //User defined
   uart_config.hwfc = NRF_UART_HWFC_DISABLED; //User defined
   uart_config.interrupt_priority = APP_IRQ_PRIORITY_LOWEST; //User defined
   uart_config.parity = NRF_UART_PARITY_EXCLUDED; //User defined
   uart_config.pselcts = CTS_PIN_NUMBER; //User defined. Remove this line if flow control is disabled.
   uart_config.pselrts = RTS_PIN_NUMBER; //User defined. Remove this line if flow control is disabled.
   uart_config.pselrxd = RX_PIN_NUMBER; //User defined
   uart_config.pseltxd = TX_PIN_NUMBER; //User defined

uint32_t err_code = nrf_drv_uart_init(&m_uart, &uart_config, uart_event_handler);
   APP_ERROR_CHECK(err_code);
}

The number of pins linked to this peripheral can be 2(flow control disabled) or 4(flow control enabled). If flow ccontrol is disabled don’t include the pin definition in the structure for RTS and CTS.

Add Initialize Function to main function call

uart_init(); // After default definition, before Advertise Start

Conclusion

With the above steps anyone can easily get started with incorporating UART

NOTE

There is another easier method to initialize and auto-generate code for nRF52. This tool, will handle all library additions and code generations for a variety of peripherals like SPI, I2C, UART etc.

Link: https://vicara.co/nrf52-code-generator