4.2.2 12-bit ADC

12-bit Analog-to-Digital Converter

4.2.2.1 Introduction

This Analog-to-Digital Converter (ADC) module is a 12-bit Successive Approximation Register (SAR) ADC, with a sampling rate up to 130 ksps at a 12-bit resolution. It can be operated in single-ended or differential conversion mode. The ADC input channels are also configurable to use internal peripheral outputs or external analog input pins.

4.2.2.2 Supported Device Families

AVR® Dx ATtiny ATmega16xx ATmega48xx
AVR®EA ATmega80x ATmega88xx

4.2.2.3 Required header files:

#include "mcc_generated_files/adc/adc[X].h"
Note: Replace [X] with the selected instance of the ADC module.

4.2.2.4 How to Use the ADC PLIB Driver

The links below provide examples for the different use cases of the ADC Peripheral Library (PLIB) Driver.

General instructions common for all examples: 4.2.2.5.2.1 ADC Use Case Code Snippet Instructions

Table 4-25. Running the ADC 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:

4.2.2.5 Module Documentation

4.2.2.5.1 ADCx

This file contains the API prototypes and other data types for the ADCx module driver.

Module description

This file contains the API prototypes and other data types for the ADCx module driver.

Version: ADC0 Driver Version 1.0.0
Typedefs
  • typedef void(* adc_irq_cb_t) (void)

    Function pointer to callback function called by IRQ. NULL=default value: No callback function is to be used.

  • typedef uint16_t adc_result_t

    Data type for the result of non-differential ADC conversion.

  • typedef int16_t diff_adc_result_t

    Data type for the result of differential ADC conversion.

  • typedef ADC_MUXPOS_t adc_0_channel_t

    Data type for the ADC Positive Input Selection.

  • typedef ADC_MUXNEG_t adc_0_muxneg_channel_t

    Data type for the ADC Negative Input Selection.

Functions

Typedef Documentation

adc_0_channel_t

ADC_MUXPOS_t adc_0_channel_t

Data type for the ADC Positive Input Selection.

adc_irq_cb_t

void adc_irq_cb_t

Function pointer to callback function called by IRQ. NULL=default value: No callback function is to be used.

adc_result_t

uint32_t adc_result_t

Data type for the result of non-differential ADC conversion.

diff_adc_result_t

int32_t diff_adc_result_t

Data type for the result of differential ADC conversion.

Function Documentation

ADCx_Disable()

void ADCx_Disable (void )

Disables the ADC0. Disables the ADC module by clearing the Enable bit in the ADC Control register. If supported by the clock system, this also disables the clock of the ADC.

Parameters:
None.
Returns:

None.

ADCx_DisableAutoTrigger()

void ADCx_DisableAutoTrigger (void )

Disables the conversion auto-trigger.

Parameters:
None.
Returns:

None.

ADCx_Enable()

void ADCx_Enable (void )

Enables the ADC0. If supported by the clock system, it enables the clock of the ADC. Enables the ADC module by setting the Enable bit in the ADC Control register.

Parameters:
None.
Returns:

None.

ADCx_EnableAutoTrigger()

void ADCx_EnableAutoTrigger (void )

Enables the conversion auto-trigger.

Parameters:
None.
Returns:

None.

ADCx_GetConversion()

adc_result_t ADCx_GetConversion (adc_0_channel_t channel)

Starts a conversion, waits until it is ready, and returns the conversion result.

Parameters:
adc_0_channel_t

channel - The ADC channel to get the conversion result.

Returns:

adc_result_t - Conversion result read from the ADC0 ADC module.

ADCx_GetConversionResult()

adc_result_t ADCx_GetConversionResult (void )

Reads a conversion result from the ADC0.

Parameters:
None.
Returns:

adc_result_t - Conversion result read from the ADC0 module.

ADCx_GetDiffConversion()

diff_adc_result_t ADCx_GetDiffConversion (adc_0_channel_t channel, adc_0_muxneg_channel_t channel1)

Starts a differential conversion, waits until ready, and returns the conversion result.

Parameters:
adc_0_channel_t

channel - The ADC positive input channel to get the conversion result.

adc_0_muxneg_channel_t

channel1 - The ADC negative input channel to get the conversion result.

Returns:

diff_adc_result_t - Conversion result read from the ADC0 ADC module.

ADCx_GetResolution()

uint8_t ADCx_GetResolution (void )

Returns the number of bits in the ADC conversion result.

Parameters:
None.
Returns:

uint8_t - The number of bits in the ADC conversion result.

ADCx_GetWindowResult()

bool ADCx_GetWindowResult (void )

Reads the conversion window result from the ADC0.

Parameters:
None.
Return values:
True

- A comparison results in a trigger condition.

False

- A comparison does not result in a trigger condition.

ADCx_Initialize()

int8_t ADCx_Initialize (void )

Initializes the ADC. If the module is configured to the Disabled state, the clock to the ADC is disabled as well, if this is supported by the device's clock system.

Parameters:
None.
Return values:
0

- The ADC init was successful.

1

- The ADC init was not successful.

ADCx_IsConversionDone()

bool ADCx_IsConversionDone (void )

Checks if the ADC conversion is done.

Parameters:
None.
Return values:
True

- The ADC conversion is done.

False

- The ADC converison is not done.

ADCx_RegisterResrdyCallback()

void ADCx_RegisterResrdyCallback (adc_irq_cb_t f)

Registers a callback function to be called when a measurement is complete and a new result is ready.

Parameters:
adc_irq_cb_t

f - Pointer to the function to be called.

Returns:

None.

ADCx_RegisterWindowCallback()

void ADCx_RegisterWindowCallback (adc_irq_cb_t f)

Registers a callback function to be called if the conversion satisfies the window criteria.

Parameters:
adc_irq_cb_t

f - Pointer to the function to be called.

Returns:

None.

ADCx_SetWindowChannel()

void ADCx_SetWindowChannel (adc_0_channel_t channel)

Sets the ADC channel to be used for Windowed Conversion mode.

Parameters:
adc_0_channel_t

channel - The ADC channel to start conversion on.

Returns:

None.

ADCx_SetWindowHigh()

void ADCx_SetWindowHigh (adc_result_t high)

Sets the conversion window comparator high threshold.

Parameters:
adc_result_t

high - Desired window comparator high threshold register value.

Returns:

None.

ADCx_SetWindowLow()

void ADCx_SetWindowLow (adc_result_t low)

Sets the conversion window comparator low threshold.

Parameters:
adc_result_t

low - Desired window comparator low threshold register value.

Returns:

None.

ADCx_SetWindowMode()

void ADCx_SetWindowMode (ADCx_window_mode_t mode)

Sets the Conversion Window mode.

Parameters:
ADCx_window_mode_t

mode - Window mode

Returns:

None.

ADCx_StartConversion()

void ADCx_StartConversion (adc_0_channel_t channel)

Starts a conversion on the ADC0.

Parameters:
adc_0_channel_t

channel - The ADC channel to start conversion on.

Returns:

None.

ADCx_StartDiffConversion()

void ADCx_StartDiffConversion (adc_0_channel_t channel, adc_0_muxneg_channel_t channel1)

Starts a differential conversion on the ADC0.

Parameters:
adc_0_channel_t

channel - The ADC positive input channel to start conversion on.

adc_0_muxneg_channel_t

channel1 - The ADC negative input channel to start conversion on.

Returns:

None.

ADCx_StopConversion()

void ADCx_StopConversion (void )

Stops a conversion on the ADC0.

Parameters:
None.
Returns:

None.

Enumeration Type Documentation

ADCx_window_mode_t

enum ADCx_window_mode_t

Window Comparator Modes.

ADCx_window_disabled

Window Comparison is Disabled

ADCx_window_below

Result is below a threshold

ADCx_window_above

Result is above a threshold

ADCx_window_inside

Result is inside a window

ADCx_window_outside

Result is outside a window

4.2.2.5.2 ADC Use Cases

ADC Use Case Code Snippet Instructions

For new users, it is recommended to start with the Timer/Counter A, UART and Data Streamer, since these components are used to support other use cases.

The use cases show examples of the ADC PLIB Driver, within an MCC Melody project:
  • Add ADC to the project

  • Configure:
    1. The ADCx 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

ADC Use Case 1: Basic conversion with Printf

An ADC conversion is taken every 100 ms, on the selected analog channel. After each ADC conversion a LED is toggled and the ADC Result is sent to PC terminal using printf.

  • Device Resources:
    1. Add ADC

    2. Add UART

  • Configuration:

  • ADC, Clock Settings:
    1. Clock Pre-Scaler: Check ADC Clock (Hz) < 2 Mhz.

  • ADC, Hardware Settings:
    1. Left Adjust Result: No.

    2. Reference select (if no separate VREF component): Select based on analog input (VDD is a good default).

  • VREF
    1. Enable Force ADC Voltage Reference: Yes.

    2. ADC Voltage Reference Source: Select based on analog input (VDD is a good default).

  • 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 an ANx.

    2. Pins: Input/Sense Configuration [ISC]: AIx pin (Digital Input buffer disabled).

    3. Pin Grid View: Select pin for UART Transmit - Tx.

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

    5. 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:

#include "mcc_generated_files/system/system.h"
#include <util/delay.h>
int main(void)
{
    adc_result_t adcResult;
    SYSTEM_Initialize();

    while(1)
    {
        adcResult = ADC0_GetConversion(ADC_MUXPOS_AIN4_gc);  //Check the schematic for your board
        LED_Toggle();
        printf("ADC result is: %2d\r\n", adcResult);
        
        _delay_ms(100); 
    }
}

ADC Use Case 2: Basic mode, with Data Streamer

An ADC conversion is taken, on the selected analog channel, every 100 ms.
  • ADC conversions are triggerd by a timer overflow callback, where the Data Streamer variables, adcResult and adcSampleCount, are updated.

  • After each ADC conversion a LED is toggled and SEND_FRAME is set to true, so that a frame is sent to the Data Visualizer from the main while loop.

Data Streamer and Timer Configurations:
  • Timer Use Case: 100 ms Timer

  • Data Streamer Use Case: Send Frames at a Period Set by the Timer

  • Device Resources:
    1. Add ADC

    2. Add Data Streamer

    3. Add Timer/Counter A (TCAx)

  • Configuration:

  • ADC, Clock Settings:
    1. Clock Pre-Scaler: Check ADC Clock (Hz) < 2 Mhz

  • ADC, Hardware Settings:
    1. Left Adjust Result: No.

    2. Reference select (if no separate VREF component): Select based on analog input (VDD is a good default).

  • VREF:
    1. Enable Force ADC Voltage Reference: Yes

    2. ADC Voltage Reference Source: Select based on analog input (VDD is a good default).

  • TCAx:
    1. Clock Selection: System Clock/x => Select so possible period > needed

    2. Requested Timeout(s): 0.1 (100 ms).

    3. Enable Overflow Interrupt: Yes

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

  • Data Streamer Table:
    1. uint16_t adcResult

    2. uint8_t adcSampleCount

  • System > Interrupt Manager
    1. Global Interrupt Enable: Yes

  • System > Pins, for all pins check board schematics:
    1. Pin Grid View: Select an ANx.

    2. Pins: Input/Sense Configuration [ISC]: AIx pin (Digital Input buffer disabled)

    3. Pin Grid View: Select pin for UART Transmit - Tx.

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

    5. 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:

#include "mcc_generated_files/system/system.h"

/* Create a pointer of the type TMR_INTERFACE and assign it to the address of the TCA0_Interface TMR_INTERFACE struct.
This enables us to access the portable API interface, which ensures changing the peripheral instance of the timer runs on is easy. */
const struct TMR_INTERFACE *Timer = &TCA0_Interface;
volatile bool SEND_FRAME = false;
void Timer_Callback_100ms(void){
    DataStreamer.adcResult = ADC0_GetConversion(ADC_MUXPOS_AIN4_gc); //Get the conversion result
    DataStreamer.adcSampleCount++;
    LED_Toggle();
    SEND_FRAME = true;
}
int main(void)
{
    SYSTEM_Initialize();
    
    DataStreamer.adcSampleCount = 0;
    DataStreamer.adcResult = 0;
    
    Timer->TimeoutCallbackRegister(Timer_Callback_100ms);
    
    while(1)
    {
        if(SEND_FRAME){
            WriteFrame();
            SEND_FRAME = false;
        }
    }
}

ADC Use Case 2.5: Accumulator mode, with Data Streamer

Run the use case above, without the accumulator and bit shifting, described below, to see the difference that these changes make to the ADC's conversion results.

  • ADC, Clock Settings:
    1. Sample Accumulation Number: 16 (then try with 64)

When the accumulator is used, for 16 or more samples, add the following line of code:

void Timer_Callback_100ms(void){
    DataStreamer.adcResult = ADC0_GetConversion(ADC_MUXPOS_AIN4_gc); 
    DataStreamer.adcResult = DataStreamer.adcResult >> 4;      //Bit shift by 4 for >= 16 accumulated samples
    DataStreamer.adcSampleCount++;
    LED_Toggle();
    SEND_FRAME = true;
}

ADC Use Case 3: Windowed ADC, on RTC overflow

An ADC conversion is started in a Real-Time Counter (RTC) overflow callback. The ADC is configured in Window mode, only taking samples when < 1v or > 2.5v.

  • Device Resources:
    1. Add ADC

    2. Add Real Time Counter (RTC)

    3. Add Data Streamer

  • ADC, Hardware Settings:
    1. Left Adjust Result: No.

    2. Reference select (if no separate VREF component): Select based on analog input (VDD is a good default).

  • ADC, Interrupt Settings:
    1. Window Comparator Interrupt: Yes.

  • ADC, Window Settings:
    1. Window Comparator Mode: Outside Window.

    2. Enable IRQ on Conversion Satisfying Window Criteria: Yes.

    3. Window Comparator High Threshold(V): 2.5(V).

    4. Window Comparator Low Threshold(V): 1(V).

  • VREF
    1. Enable Force ADC Voltage Reference: Yes

    2. Select based on analog input (VDD is a good default).

  • RTC, Hardware Settings:
    1. Period (s): 0.05(s).

  • RTC, Interrupt Settings:
    1. Overflow Interrupt Enable: Yes.

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

  • Data Streamer Table:
    1. uint16_t adcResult

    2. uint8_t adcWindowCount

  • System > Interrupt Manager
    1. Global Interrupt Enable: Yes

  • System > Pins, for all pins check board schematics:
    1. Pin Grid View: Select an ANx.

    2. Pins: Input/Sense Configuration [ISC]: AIx pin (Digital Input buffer disabled)

    3. Pin Grid View: Select pin for UART Transmit - Tx.

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

    5. 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:

#include "mcc_generated_files/system/system.h"

volatile bool SEND_FRAME = false;
void Window_Callback(void){
    LED_SetLow();
    DataStreamer.adcResult = ADC0_GetConversionResult();
    DataStreamer.adcWindowCount++;
    SEND_FRAME = true;
}

void RTC_Callback(void){
    ADC0_StartConversion(ADC_MUXPOS_AIN4_gc);
}
int main(void)
{
    SYSTEM_Initialize();
    RTC_SetOVFIsrCallback(RTC_Callback);
    ADC0_RegisterWindowCallback(Window_Callback);
    
    DataStreamer.adcResult = 0;
    DataStreamer.adcWindowCount = 0;

    while(1)
    {
        if(SEND_FRAME){
            WriteFrame();
            LED_SetHigh();
            SEND_FRAME = false;
        }
        
    }
}

ADC Use Case 3.5: Event Triggered ADC Conversions

Refactoring the use case above (Windowed ADC on an RTC overflow) to use the Event System (EVSYS) to trigger ADC conversions. Since the EVSYS makes direct hardware connections between the peripherals, the RTC callback (and its registration) can be removed.

Modification of previous use case:

  • Device Resources:
    1. Add EVSYS (Event System)

  • ADC > Hardware Settings:
    1. Positive Input Selection: ADC input pin x //Select based on your schematics

    2. Start Event Input Enable: Yes.

  • RTC > Hardware Settings:
    1. Overflow Interrupt Enable: No.

  • EVSYS Configuration:
    1. GENERATORS: RTC_OVF -> CHANNELS: CHANNEL0

    2. USERS: ADC0START -> CHANNELS: CHANNEL0

#include "mcc_generated_files/system/system.h"

volatile bool SEND_FRAME = false;
void Window_Callback(void){
    LED_SetLow();
    DataStreamer.adcResult = ADC0_GetConversionResult();
    DataStreamer.adcWindowCount++;
    SEND_FRAME = true;
}
int main(void)
{
    SYSTEM_Initialize();
    ADC0_RegisterWindowCallback(Window_Callback);
    
    DataStreamer.adcResult = 0;
    DataStreamer.adcWindowCount = 0;

    while(1)
    {
        if(SEND_FRAME){
            WriteFrame();
            LED_SetHigh();
            SEND_FRAME = false;
        }
        
    }
}

4.2.2.6 File Documentation

4.2.2.6.1 source/adc.dox File Reference

4.2.2.6.2 source/adc0.c File Reference

API Implementations for ADCx module driver.

#include "../adc0.h"

Functions

Detailed Description

API Implementations for ADCx module driver.

ADC0 Generated Driver File

Version: ADC0 Driver Version 1.0.0

Function Documentation

ISR()[1/2]

ISR (ADC0_WCMP_vect )

ISR()[2/2]

ISR (ADC0_RESRDY_vect )

Variable Documentation

4.2.2.6.3 source/adc0.h File Reference

#include "../system/utils/compiler.h"

Functions

Typedefs

  • typedef void(* adc_irq_cb_t) (void)

    Function pointer to callback function called by IRQ. NULL=default value: No callback function is to be used.

  • typedef uint16_t adc_result_t

    Data type for the result of non-differential ADC conversion.

  • typedef int16_t diff_adc_result_t

    Data type for the result of differential ADC conversion.

  • typedef ADC_MUXPOS_t adc_0_channel_t

    Data type for the ADC Positive Input Selection.

  • typedef ADC_MUXNEG_t adc_0_muxneg_channel_t

    Data type for the ADC Negative Input Selection.

Detailed Description

ADC0 Generated Driver API Header File