2.5 Analog Front-End Controller (AFEC)

  • 12-bit Resolution up to 16-bit Resolution by Digital Averaging

  • Wide Range of Power Supply Operation

  • Selectable Single-ended or Differential Input Voltage

  • Selectable Single or Dual Sample-and-Hold Mode

  • Programmable Gain for Maximum Full-Scale Input Range 0–VDD

  • Programmable Offset Per Channel

  • Automatic Correction of Offset and Gain Errors

  • Integrated Multiplexers Offering Up to 12 Independent Analog Inputs

  • Individual Enable and Disable of Each Channel

  • Hardware or Software Trigger (External trigger pin, Timer counter outputs (corresponding TIOA trigger), PWM event line)

  • Drive of PWM Fault Input

  • DMA Support

  • Possibility of AFE Timings Configuration

  • Two Sleep Modes and Conversion Sequencer (Automatic wakeup on trigger and back to sleep mode after conversions of all enabled channels, Possibility of customized channel sequence)

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

/*****************************************************
 AFEC CH0 - PB01 - Connect to DACC output PB13
 AFEC CH5 - PC30 - connect to Vcc
 AFEC_CH6 - PC31 - Connect to GND
 *****************************************************/

#define AFEC_VREF               (3.3f)
#define DAC_COUNT_INCREMENT     (124U)  // Equivalent to 0.1V 
#define DAC_COUNT_MAX           (4095U)


volatile uint16_t adc_ch0_count, adc_ch5_count, adc_ch6_count;

float adc_ch0_voltage, adc_ch5_voltage, adc_ch6_voltage;

volatile bool result_ready;
/* Initial DAC count which is midpoint = 1.65V*/
uint16_t dac_count=0x800; 


void switch_handler( PIO_PIN pin, uintptr_t context )
{
    /* Write next data sample */
    dac_count = dac_count + DAC_COUNT_INCREMENT;
    
    if (dac_count > DAC_COUNT_MAX)
            dac_count=0;    
    
    DACC_DataWrite(DACC_CHANNEL_0, dac_count);
}

/* This function is called after conversion of last channel in the user sequence */
void AFEC_EventHandler(uint32_t status, uintptr_t context)
{
    /* Read the result of 3 channels*/
    adc_ch5_count = AFEC1_ChannelResultGet(CH5_VDD);
    adc_ch6_count = AFEC1_ChannelResultGet(CH6_GND);
    adc_ch0_count = AFEC1_ChannelResultGet(CH0_SINE_WAVE);
       
    result_ready = true;

}

// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );
    
    PIO_PinInterruptCallbackRegister(SWITCH_PIN, &switch_handler, (uintptr_t) NULL );
    PIO_PinInterruptEnable(SWITCH_PIN);

    /* Register callback function for AFEC end of conversion interrupt*/
    AFEC1_CallbackRegister(AFEC_EventHandler, (uintptr_t)NULL);
    
    /* Write first data sample in DAC channel 0 and channel 1*/
    DACC_DataWrite(DACC_CHANNEL_0, dac_count);
    
    /* Start the timer to trigger ADC conversion every 50 ms*/
    TC1_CH0_CompareStart();

    printf("\n\r---------------------------------------------------------");
    printf("\n\r                    AFEC User Sequence Demo                 ");
    printf("\n\r---------------------------------------------------------\n\r");
    printf("CH0 Count  CH0 Voltage  CH5 Count  CH5 Voltage  CH6 Count  CH6 Voltage \n\r");           

    while ( true )
    {
        /* Check if result is ready to be transmitted to console */
        if (result_ready == true)
        {
            adc_ch5_voltage = (float)adc_ch5_count * AFEC_VREF/4095U;
            adc_ch6_voltage = (float)adc_ch6_count * AFEC_VREF/4095U;
            adc_ch0_voltage = (float)adc_ch0_count * AFEC_VREF/4095U;
            printf("0x%03x      %0.2f V       0x%03x      %0.2f V       0x%03x      %0.2f V \t\r", \
                    adc_ch0_count, adc_ch0_voltage, adc_ch5_count, adc_ch5_voltage, adc_ch6_count, adc_ch6_voltage);
                           
                
            result_ready = false;
        }
    }

    /* 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 <stdio.h>
#include "definitions.h"                // SYS function prototypes

#define AFEC_VREF               (3.3f)
#define DAC_COUNT_INCREMENT     (124U)  // equivalent to 0.1V 
#define DAC_COUNT_MAX           (4095U)

uint16_t adc_count;
float input_voltage;
/* Initial value of dac count which is midpoint = 1.65 V*/
uint16_t dac_count = 0x800;   


void switch_handler( PIO_PIN pin, uintptr_t context )
{
    /* Write next data sample */
    dac_count = dac_count + DAC_COUNT_INCREMENT;
    
    if (dac_count > DAC_COUNT_MAX)
            dac_count=0;    
    
    DACC_DataWrite(DACC_CHANNEL_0, dac_count);
}

// *****************************************************************************
// *****************************************************************************
// Section: Main Entry Point
// *****************************************************************************
// *****************************************************************************

int main ( void )
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );
    
    PIO_PinInterruptCallbackRegister(SWITCH_PIN, &switch_handler, (uintptr_t) NULL );
    PIO_PinInterruptEnable(SWITCH_PIN);
    
    printf("\n\r---------------------------------------------------------");
    printf("\n\r                    AFEC Demo                 ");
    printf("\n\r---------------------------------------------------------\n\r");
    printf("Press switch to change the DAC output. \r\n");
    
    SYSTICK_TimerStart();

    DACC_DataWrite(DACC_CHANNEL_0, dac_count);
        
    while (1)
    {
        /* Start ADC conversion */
        AFEC1_ConversionStart();

        /* Wait till ADC conversion result is available */
        while(!AFEC1_ChannelResultIsReady(AFEC_CH0))
        {

        };

        /* Read the ADC result */
        adc_count = AFEC1_ChannelResultGet(AFEC_CH0);
        input_voltage = (float)adc_count * AFEC_VREF / 4095U;

        printf("ADC Count = 0x%03x, ADC Input Voltage = %0.2f V \r",adc_count, input_voltage);    
        
        SYSTICK_DelayMs(500);
    }
    
    /* Execution should not come here during normal operation */

    return ( EXIT_FAILURE );
}

Library Interface

Analog Front-End Controller peripheral library provides the following interfaces:

Functions

NameDescription
AFECx_InitializeInitializes given instance of AFEC peripheral
AFECx_ChannelsEnableEnables the ADC channels
AFECx_ChannelsDisableDisables the ADC channels
AFECx_ChannelsInterruptEnableEnables the ADC interrupt sources
AFECx_ChannelsInterruptDisableDisables the ADC interrupt sources
AFECx_ConversionStartStarts the ADC conversion of all the enabled channels with the software trigger
AFECx_ChannelResultIsReadyReturns the status of the channel conversion
AFECx_ChannelResultGetReads the conversion result of the channel
AFECx_ConversionSequenceSetSets the user sequence of the channel conversion
AFECx_ChannelGainSetWrites the gain of the channel
AFECx_ChannelOffsetSetWrites the channel offset
AFECx_CallbackRegisterRegisters the function to be called from interrupt

Data types and constants

NameTypeDescription
AFEC_CHANNEL_NUMEnumIdentifies AFEC channel number
AFEC_INTERRUPT_MASKEnumIdentifies channel interrupt sources mask
AFEC_CHANNEL_MASKEnumIdentifies AFEC channel mask
AFEC_CHANNEL_GAINEnumIdentifies programmable gain setting
AFEC_CALLBACKTypedefDefines the function pointer data type and function signature for the afec peripheral callback function
AFEC_CALLBACK_OBJECTStructAFEC Callback structure
Note: Not all APIs maybe implemented. See the specific device family section for available APIs.