| nRF5 SDK v12.0.0 |

Choose documentation: | nRF5 SDK | S130 SoftDevice API | S132 SoftDevice API | S212 SoftDevice API | S332 SoftDevice API

All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
SAADC
This information applies to the nRF52 Series only.

The SAADC driver includes two layers: the hardware access layer (HAL) and the driver layer (DRV).

The hardware access layer provides basic APIs for accessing the registers of the SAADC peripheral. See the API documentation for the SAADC HAL for details.

The driver layer provides APIs on a higher level than the HAL. See the API documentation for the SAADC driver for details.

Key features include:

- Blocking function to convert one sample on a single channel.
- Non-blocking function for triggering conversion on all enabled channels to a provided buffer.
- Double buffering: you can set up two buffers, and conversion to the new buffer starts immediately after the first one is filled.

# Driver configuration

The SAADC default configuration is located in `sdk_config.h`. The SAADC must be explicitly enabled in `sdk_config.h` before the driver can be used. If nrf_drv_saadc_init is called with a NULL pointer to the configuration structure, the default configuration from `sdk_config.h` is used. You must provide an event handler function during initialization.

Driver configuration includes:

- Resolution
- Enabling or disabling oversampling
- Interrupt priority level
- Enabling or disabling the low power mode

Note
  If oversampling is enabled, only one channel can be enabled. nrf_drv_saadc_channel_init asserts if this condition is not met.

Each channel is configured independently. Channels are configured and enabled by the function nrf_drv_saadc_channel_init. NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE or NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_DIFFERENTIAL can be used to build a default configuration for a channel.

Example:

nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6);
channel_config.gain = NRF_SAADC_GAIN1_2;
//Initialization and enabling of channel 0 to use analog input 6.
err_code = nrf_drv_saadc_channel_init(0, &channel_config);

nrf_drv_saadc_gpio_to_ain can be used to convert a GPIO pin number to an analog input number.

# Using the SAADC driver

The SAADC driver can be used in blocking mode or non-blocking mode.

## Blocking mode

The function nrf_drv_saadc_sample_convert is blocking and returns when the requested channel is sampled. The channel must be initialized before it can be used. If the SAADC is busy, the function returns with an error. In blocking mode, the driver does not use the peripheral interrupt and there is no context switching inside the driver.

## Non-blocking mode

The function nrf_drv_saadc_buffer_convert can be used to start conversion in non-blocking mode. The function returns immediately after the buffer is configured. If the driver is busy, it returns with an error. nrf_drv_saadc_buffer_convert sets the SAADC up for conversion, but does not trigger sampling. To trigger sampling, call the function nrf_drv_saadc_sample or, through PPI, use the task SAMPLE from SAADC. nrf_drv_saadc_sample_task_get can be used to get the task address. Single sampling triggers conversion on all initialized channels. When the requested buffer is filled with samples, an event of type NRF_DRV_SAADC_EVT_DONE is generated.

To enable the low power mode, you must specify this option when initializing the driver. You can do it by setting SAADC_CONFIG_LP_MODE to true in the driver initialization configuration structure. When it is enabled, the driver uses less power, but more interrupts are generated. When using this mode, the parameter size of function nrf_drv_saadc_buffer_convert must be a multiple of the number of enabled channels. Otherwise, undefined behavior may occur.

Example for sampling triggered by the CPU:

err_code = nrf_drv_saadc_buffer_convert(buffer, 1);
//Check error.
err_code = nrf_drv_saadc_sample();
//Check error.
//Event handler is called immediately after conversion is finished.

Example for setting up sampling by PPI:

err_code = nrf_drv_saadc_buffer_convert(buffer, length);
//Check error.
uint32_t sample_task = nrf_drv_saadc_sample_task_get();
//Set task end point in PPI using sample_task variable.

The driver supports double buffering, which means that nrf_drv_saadc_buffer_convert can be called twice and the buffer that is provided in the second call will be used immediately after the first one is filled.

Continuous conversion can be achieved by setting up two buffers and calling nrf_drv_saadc_buffer_convert again in the event handler to switch between them later.

Example for setting up two buffers:

err_code = nrf_drv_saadc_buffer_convert(buffer1, length1);
//Check error.
err_code = nrf_drv_saadc_buffer_convert(buffer2, length2);
//Check error.

Example for setting up a completed buffer again in the event handler:

void event_handler(nrf_drv_saadc_evt_t * p_event)
{
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
//Check error.
}
}

To configure the SAADC to continue conversion to the second buffer, SAADC interrupts must be handled. However, if only one channel is used, EasyDMA could automatically start processing using the second buffer if PPI is used to bind SAADC END events with the SAADC START task. This is not done by the driver because it is only controlling the SAADC peripheral, but it can be done in the application code.

## Limits

The driver can generate events of type NRF_DRV_SAADC_EVT_LIMIT if the converted sample on a given channel is exceeding a limit. You can set two limits per channel: high and low. The function nrf_drv_saadc_limits_set can be used to configure these limits. The function sets both limits; if only one limit should be enabled, the second can be disabled by using NRF_DRV_SAADC_LIMITH_DISABLED for the high limit or NRF_DRV_SAADC_LIMITL_DISABLED for the low limit.

The limit event will be generated by every sample that exceeds the limit. If this is not desired, it can be disabled in the event handler.