Microchip® Advanced Software Framework

Event-triggered conversions

In this use case, ADCA is configured for:

  • sampling on two channels (0 and 1) with respective inputs:
    • internal temperature sensor
    • internal bandgap reference
  • unsigned conversions
  • 12-bit resolution
  • VCC/1.6 as voltage reference
  • event-triggered conversions
  • polled conversion handling

Completed conversions are detected via non-blocking polling of the interrupt flags. The ADC results are stored into local variables as soon as they are available.

A Timer/Counter is used to generate events that trigger the conversions.

Note
This use case assumes that the device has multiple ADC channels. Refer to the applicable device datasheet for information about the number of ADC channels.

Setup steps

Prerequisites

This use case requires that the Timer/Counter driver is added to the project.

Example code

Add to application C-file:

#define MY_ADC ADCA
#define MY_TIMER TCC0
static void evsys_init(void)
{
EVSYS.CH3MUX = EVSYS_CHMUX_TCC0_OVF_gc;
}
static void tc_init(void)
{
tc_enable(&MY_TIMER);
tc_set_wgm(&MY_TIMER, TC_WG_NORMAL);
tc_write_period(&MY_TIMER, 200);
tc_set_resolution(&MY_TIMER, 2000);
}
static void adc_init(void)
{
struct adc_config adc_conf;
struct adc_channel_config adcch_conf;
adc_read_configuration(&MY_ADC, &adc_conf);
adcch_read_configuration(&MY_ADC, ADC_CH0, &adcch_conf);
adc_set_clock_rate(&adc_conf, 200000UL);
adc_write_configuration(&MY_ADC, &adc_conf);
adcch_write_configuration(&MY_ADC, ADC_CH0, &adcch_conf);
adcch_write_configuration(&MY_ADC, ADC_CH1, &adcch_conf);
}

Add to main():

evsys_init();
adc_init();

Workflow

  1. Add macros for the ADC and the conversion trigger timer to use, so they are easy to change:
    • #define MY_ADC ADCA
      #define MY_TIMER TCC0
  2. Create a function evsys_init() to intialize the event system clocks and to link the conversion timer to the correct event channel:
    • static void evsys_init(void)
      {
      // ...
      }
  3. Use the sysclk service to enable the clock to the event system:
  4. Connect the TCC0 overflow event to event channel 3:
    • EVSYS.CH3MUX = EVSYS_CHMUX_TCC0_OVF_gc;
      Note
      If the ADC trigger timer is changed from TCC0, the EVSYS_CHMUX_* mask here will also need to be altered.
  5. Create a function tc_init() to intialize the ADC trigger timer:
    • static void tc_init(void)
      {
      // ...
      }
  6. Enable the clock to the ADC trigger timer:
  7. Configure the ADC trigger timer in normal Waveform Generation mode:
  8. Configure the ADC trigger timer period to overflow at 200 counts:
  9. Configure the ADC trigger timer resolution (frequency) for 2KHz:
  10. Create a function adc_init() to intialize the ADC ready for conversions on channels 0 and 1, triggered by the event system:
    • static void adc_init(void)
      {
      // ...
      }
  11. Allocate configuration structs for ADC and channel, then initialize them:
  12. Set unsigned, 12-bit conversions with internal VCC/1.6 voltage reference:
  13. Set event system triggered conversions on the first two ADC channels, with conversions triggered by event system channel 3:
  14. Turn on the internal bandgap and temperature sensor ADC inputs:
  15. Set ADC clock rate to maximum 200 KHz:
  16. Write the configuration to the ADC:
  17. Set up single-ended input from the internal temperature sensor, then write the config to the first channel (0):
  18. Set up single-ended input from the internal bandgap voltage, then write the config to the second channel (1):
  19. Initialize the clock system, event system, ADC trigger timer, and the ADC:

Usage steps

Example code

Add to main():

adc_enable(&MY_ADC);
do {
uint16_t tmp_result;
uint16_t bg_result;
== (ADC_CH0 | ADC_CH1)) {
tmp_result = adc_get_result(&MY_ADC, ADC_CH0);
bg_result = adc_get_result(&MY_ADC, ADC_CH1);
}
} while (true);

Workflow

  1. Enable the configured ADC module, so that it will begin conversions when triggered:
  2. Create an infinite loop so that conversions will be processed forever:
    • do {
      // ...
      } while (true);
  3. Within the loop, create local variables to contain the ADC result of each channel (internal temperature sensor and internal bandgap voltage):
    • int16_t temp_result;
      int16_t bg_result;
  4. Test if both ADC channel 0 and channel 1 have completed a conversion by testing the respective channel conversion complete interrupt flags:
  5. Store the channel result values into the local variables created earlier:
  6. Clear both ADC channel conversion complete interrupt flags, so that we can detect future conversions at a later stage: