1.2.2 Analog-to-Digital Converter (ADC)

  • Up to 12-bit resolution of the numerical output, signed or unsigned

  • Signed outputs left- or right-adjusted

  • Up to 5.14 Msps conversion rate per channel

  • Up to 4 Shared Analog ADC SAR cores (bound by limited CSR and pin-out resources) for an aggregate conversion rate of 20.5 Msps per entire ADC module by performing up to 4 conversions simultaneously

  • Up to 64 analog inputs (maximum of 16 channels per core).

  • Single-ended and/or differential inputs on a per channel basis for all channels.

  • Up to 16 trigger sources, off-chip hardware or on-chip hardware or software generated

  • Edge or level active triggering modes, to generate single conversions or bursts of conversions

  • A scan trigger per each shared Analog ADC SAR Core to start a scan cycle which can individually include or not any of the analog inputs assigned to that Analog ADC SAR Core

  • Up to 4 scan cycles running simultaneously

  • Any channel can select any of the 16 trigger sources or the scan trigger as its own trigger

  • The scan trigger itself can select any of the 16 trigger sources as its own source Programmable sampling time, individual for each shared Analog ADC SAR Core

  • Each analog input / channel output register can be read from an general dedicated APB output register (user writes the CORDYID and CHRDYID then reads the CHRDYDATA register).

Using The Library

Interrupt mode:

#include <stddef.h>                     // Defines NULL
#include <stdbool.h>                    // Defines true
#include <stdlib.h>                     // Defines EXIT_FAILURE
#include "definitions.h"                // SYS function prototypes

#define ADC_VREF                             (3.3f)

volatile uint32_t adc_data[3];
volatile bool adc_sequence_done = false;
volatile bool adc_ch2_done = false;
float adc_inp_vol;
// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************
void ADC_EventHandler(ADC_CORE_INT status, uintptr_t context)
{
    /* ADC1_CH0 and ADC1_CH1 are configured for scan trigger */
    if (status & ADC_CORE_INT_EOSRDY)
    {                
        adc_data[0] = ADC_ResultGet(ADC_CORE_NUM1, ADC_CH0);
        
        adc_data[1] = ADC_ResultGet(ADC_CORE_NUM1, ADC_CH1);
        
        adc_sequence_done = true;
    }
    /* ADC1_CH2 is configured for Global (Edge) Software trigger */
    if (status & ADC_CORE_INT_CHRDY_2)
    {
        adc_data[2] = ADC_ResultGet(ADC_CORE_NUM1, ADC_CH2);
        
        adc_ch2_done = true;
    }
}

int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );
    
    printf("\r\n *********************************************** \r\n");
    printf("\r\n           ADC INTERRUPT DEMO \r\n");
    printf("\r\n *********************************************** \r\n");
    
    ADC_CORE1CallbackRegister(ADC_EventHandler, 0);    
    RTC_Timer32Start();

    while ( true )
    {
        if (SWITCH_Get() == 0)
        {
            // Wait for switch release
            while (SWITCH_Get() == 0);
            
            ADC_GlobalEdgeConversionStart();
        }
        
        if (adc_sequence_done == true) 
        {
			adc_sequence_done = false;
                                    
            adc_inp_vol = (uint16_t)adc_data[0] * ADC_VREF / 4095U;
            
            printf("\r\n ADC1_AIN0: ADC Count: 0x%03x, ADC Input Voltage = %d.%02d V \r\n", 
                    (uint16_t)adc_data[0], (int)adc_inp_vol, (int)((adc_inp_vol - (int)adc_inp_vol)*100.0));
            
            adc_inp_vol = (uint16_t)adc_data[1] * ADC_VREF / 4095U;
            
            printf("\r\n ADC1_AIN1: ADC Count: 0x%03x, ADC Input Voltage = %d.%02d V \r\n", 
                    (uint16_t)adc_data[1], (int)adc_inp_vol, (int)((adc_inp_vol - (int)adc_inp_vol)*100.0));
		}       
        if (adc_ch2_done == true)
        {
            adc_ch2_done = false;
            
            adc_inp_vol = (uint16_t)adc_data[2] * ADC_VREF / 4095U;
            
            printf("\r\n ADC1_AIN2: ADC Count: 0x%03x, ADC Input Voltage = %d.%02d V \r\n", 
                    (uint16_t)adc_data[2], (int)adc_inp_vol, (int)((adc_inp_vol - (int)adc_inp_vol)*100.0));
        }
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}

Polling mode:

#include <stddef.h>                     // Defines NULL
#include <stdbool.h>                    // Defines true
#include <stdlib.h>                     // Defines EXIT_FAILURE
#include "definitions.h"                // SYS function prototypes

#define ADC_VREF                             (3.3f)

// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************
uint32_t adc_data;
float adc_inp_vol;

int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );
    
    while ( true )
    {
        ADC_GlobalEdgeConversionStart();
        
        while (ADC_ChannelResultIsReady(ADC_CORE_NUM1, ADC_CH0) == false);
        
        adc_data = ADC_ResultGet(ADC_CORE_NUM1, ADC_CH0);
        
        adc_inp_vol = (uint16_t)adc_data * ADC_VREF / 4095U;
            
        printf("ADC1_AIN0: ADC Count: 0x%03x, ADC Input Voltage = %d.%02d V\r", 
            (uint16_t)adc_data, (int)adc_inp_vol, (int)((adc_inp_vol - (int)adc_inp_vol)*100.0));
    }

    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}

Library Interface

ADC Controller peripheral library provides the following interfaces:

Functions

Name Description
ADCx_Initialize Initializes given instance of ADC peripheral
ADCx_Enable Enables the ADC module
ADCx_Disable Disables the ADC module
ADC_CompareEnable Enables digital comparisons for the given channel on the specified ADC core
ADC_CompareDisable Disables digital comparisons for the given channel on the specified ADC core
ADC_CompareWinThresholdSet Configures the low and high threshold values for the comparator on the specified ADC core
ADC_CompareWinModeSet Configures the low and high threshold values for the comparator on the specified ADC core
ADC_GlobalInterruptsStatusGet Returns the global interrupt status
ADC_CoreInterruptsEnable Enables the specified ADC core's interrupt
ADC_CoreInterruptsDisable Disable the specified ADC core's interrupts
ADC_CoreInterruptsStatusGet Returns the specified ADC core's interrupt status
ADC_CoreInterruptsStatusClear Clears the specified ADC core's interrupt status
ADC_GlobalEdgeConversionStart Generates global edge trigger and starts conversion on channels configured with Global edge as the trigger source
ADC_GlobalLevelConversionStart Starts global level trigger and starts conversion on channels configured with Global level as the trigger source
ADC_GlobalLevelConversionStop Stops global level trigger and stops conversion on channels configured with Global level as the trigger source
ADC_SyncTriggerEnable Enables sync trigger defined by CTRLC.CNT value
ADC_SyncTriggerDisable Disables sync trigger
ADC_SyncTriggerCounterSet Configures the value of CTRLC.CNT register
ADC_SoftwareControlledConversionEnable Enables software controlled conversion on the specified ADC core's channel
ADC_ChannelSamplingStart Enables the Analog Mux Input and starts sampling on the ADC core and channel that was specified using the ADC_SoftwareControlledConversionEnable() API
ADC_ChannelSamplingStop Stops sampling on the ADC core and channel that was specified using the ADC_SoftwareControlledConversionEnable() API
ADC_ChannelConversionStart Starts conversion on the ADC core and channel that was specified using the ADC_SoftwareControlledConversionEnable() API
ADC_ChannelResultIsReady Indicates whether ADC conversion is complete on the specified ADC core's channel
ADC_EOSStatusGet Indicates whether End of scan interrupt flag is set on the specified ADC core
ADC_ResultGet Returns the ADC conversion value for the specified ADC core channel
ADC_FIFORead Returns a single ADC conversion value from the ADC FIFO
ADC_FIFOBufferRead Returns multiple ADC conversion values from the ADC FIFO
ADC_GlobalCallbackRegister Registers the global callback function
ADC_COREnCallbackRegister Registers the ADC core specific callback function

Data types and constants

Name Type Description
ADC_CORE_INT_CMPHIT Macro Identifies ADC core interrupt status
ADC_FIFO_CORID_GET Macro Returns the ADC core id in the ADC FIFO data
ADC_FIFO_DATA_GET Macro Returns the ADC conversion resunt from the ADC FIFO data
ADC_FIFO_CHNID_GET Macro Returns the ADC channel id in the ADC FIFO data
ADC_FIFO_CNT_GET Macro Returns the current number of entries present in the ADC FIFO
ADC_GLOBAL_INT_CRRDY1 Macro Identifies ADC global interrupt status
ADC_CHANNEL_NUM Enum Identifies ADC channel number
ADC_CORE_NUM Enum Identifies ADC core
ADC_CORE_CALLBACK Typedef Defines the function pointer data type and function signature for the adc peripheral core callback function
ADC_GLOBAL_CALLBACK Typedef Defines the function pointer data type and function signature for the adc peripheral global callback function
ADC_CORE_CALLBACK_OBJECT Struct ADC Core events Callback structure
ADC_GLOBAL_CALLBACK_OBJECT Struct ADC Global Callback structure