Setting Up ADC in nRF52xx
Image for post

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

ADC

Analog to Digital Converters are a very essential component of embedded devices. Our world operates in analog format and correspondingly the sensors we develop read analog signals. However, our processors are all digital and not a good fit for handling analog data.

ADC reads analog signals and converts them into a usable format ie; digital for use in microcontrollers and microprocessors. In nRF devices, this is called SAADC. SAADC stands for Successive Approximation ADC.

Image for post

Implementing SAADC 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

Image for post

Include the SPI Driver files. This file should be titled, nrf_drv_saadc.c It is at SDK/integration/nrfx/legacy folder.

Update sdk_config.h File

  • SAADC_ENABLED has to be set to set to 1.

In main.c File

Header File

#include "nrf_drv_saadc.h"

Define Callback Function


staticvoidsaadc_callback(nrf_drv_saadc_evt_tconst * p_event)
{
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
   {
   }
}

Note: SAADC has only one instance and this function is for all the channels.


Initialize SAADC Instance


staticvoidsaadc_init()
{
ret_code_t err_code;

//VCE: The below block is for configuring the whole SAADC peripheral
nrf_drv_saadc_config_t saadc_config;
   saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOWEST;
   saadc_config.low_power_mode = false;
   saadc_config.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;
   saadc_config.resolution = NRF_SAADC_RESOLUTION_8BIT;

   err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
   APP_ERROR_CHECK(err_code);

//VCE: The next 2 blocks configure one channel as single ended and the other as differential.
nrf_saadc_channel_config_t channel_config_0;
   channel_config_0.resistor_p = NRF_SAADC_RESISTOR_DISABLED;
   channel_config_0.resistor_n = NRF_SAADC_RESISTOR_DISABLED;      
   channel_config_0.gain       = NRF_SAADC_GAIN1_6;      
   channel_config_0.reference  = NRF_SAADC_REFERENCE_INTERNAL;
   channel_config_0.acq_time   = NRF_SAADC_ACQTIME_10US;    
   channel_config_0.mode       = NRF_SAADC_MODE_SINGLE_ENDED;
   channel_config_0.burst      = NRF_SAADC_BURST_DISABLED;      
   channel_config_0.pin_p      = NRF_SAADC_INPUT_AIN0;
   channel_config_0.pin_n      = NRF_SAADC_INPUT_DISABLED;

   err_code = nrf_drv_saadc_channel_init(0, &channel_config_0);
   APP_ERROR_CHECK(err_code);

nrf_saadc_channel_config_t channel_config_1;
   channel_config_1.resistor_p = NRF_SAADC_RESISTOR_PULLDOWN;
   channel_config_1.resistor_n = NRF_SAADC_RESISTOR_PULLUP;    
   channel_config_1.gain       = NRF_SAADC_GAIN1_2;      
   channel_config_1.reference  = NRF_SAADC_REFERENCE_VDD4;
   channel_config_1.acq_time   = NRF_SAADC_ACQTIME_40US;    
   channel_config_1.mode       = NRF_SAADC_MODE_DIFFERENTIAL;
   channel_config_1.burst      = NRF_SAADC_BURST_ENABLED;      
   channel_config_1.pin_p      = NRF_SAADC_INPUT_AIN1;
   channel_config_1.pin_n      = NRF_SAADC_INPUT_AIN2;

   err_code = nrf_drv_saadc_channel_init(1, &channel_config_1);
   APP_ERROR_CHECK(err_code);
}

Note: The pin structure needs to be defined for each channel to be used and nrf_drv_saadc_channel_init needs to be called for each channel too.


Add saadc_init() to main()

saadc_init();

Conclusion

With the above steps anyone can easily get started with incorporating SAADC.

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