Microchip® Advanced Software Framework

Quick Start Guide for AC - Callback

In this use case, the Analog Comparator module is configured for:

  • Comparator peripheral in manually triggered (e.g. "Single Shot" mode)
  • One comparator channel connected to input MUX pin 0 and compared to a scaled VCC/2 voltage

This use case sets up the Analog Comparator to compare an input voltage fed into a GPIO pin of the device against a scaled voltage of the microcontroller's VCC power rail. The comparisons are made on-demand in single-shot mode, and the result stored into a local variable which is then output to the board LED to visually show the comparison state.

Setup

Prerequisites

There are no special setup requirements for this use-case.

Code

Copy-paste the following setup code to your user application:

/* AC module software instance (must not go out of scope while in use). */
static struct ac_module ac_instance;
/* Comparator channel that will be used. */
#define AC_COMPARATOR_CHANNEL AC_CHAN_CHANNEL_0
void configure_ac(void)
{
/* Create a new configuration structure for the Analog Comparator settings
* and fill with the default module settings. */
struct ac_config config_ac;
/* Alter any Analog Comparator configuration settings here if required. */
/* Initialize and enable the Analog Comparator with the user settings. */
ac_init(&ac_instance, AC, &config_ac);
}
{
/* Create a new configuration structure for the Analog Comparator channel
* settings and fill with the default module channel settings. */
struct ac_chan_config config_ac_chan;
ac_chan_get_config_defaults(&config_ac_chan);
/* Set the Analog Comparator channel configuration settings. */
config_ac_chan.sample_mode = AC_CHAN_MODE_SINGLE_SHOT;
#if (SAMR30E)
config_ac_chan.positive_input = AC_CHAN_POS_MUX_PIN2;
#else
config_ac_chan.positive_input = AC_CHAN_POS_MUX_PIN0;
#endif
config_ac_chan.negative_input = AC_CHAN_NEG_MUX_SCALED_VCC;
config_ac_chan.vcc_scale_factor = 32;
config_ac_chan.interrupt_selection = AC_CHAN_INTERRUPT_SELECTION_END_OF_COMPARE;
/* Set up a pin as an AC channel input. */
struct system_pinmux_config ac0_pin_conf;
ac0_pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
ac0_pin_conf.mux_position = CONF_AC_MUX;
system_pinmux_pin_set_config(CONF_AC_PIN, &ac0_pin_conf);
/* Initialize and enable the Analog Comparator channel with the user
* settings. */
}
void callback_function_ac(struct ac_module *const module_inst)
{
}
{
}

Add to user application initialization (typically the start of main()):

Workflow

  1. Create an AC device instance struct, which will be associated with an Analog Comparator peripheral hardware instance.
    static struct ac_module ac_instance;
    Note
    Device instance structures shall never go out of scope when in use.
  2. Define a macro to select the comparator channel that will be sampled, for convenience.
    #define AC_COMPARATOR_CHANNEL AC_CHAN_CHANNEL_0
  3. Create a new function configure_ac(), which will be used to configure the overall Analog Comparator peripheral.
    void configure_ac(void)
    {
  4. Create an Analog Comparator peripheral configuration structure that will be filled out to set the module configuration.
    struct ac_config config_ac;
  5. Fill the Analog Comparator peripheral configuration structure with the default module configuration values.
  6. Initialize the Analog Comparator peripheral and associate it with the software instance structure that was defined previously.
    ac_init(&ac_instance, AC, &config_ac);
  7. Create a new function configure_ac_channel(), which will be used to configure the overall Analog Comparator peripheral.
    {
  8. Create an Analog Comparator channel configuration structure that will be filled out to set the channel configuration.
    struct ac_chan_config config_ac_chan;
  9. Fill the Analog Comparator channel configuration structure with the default channel configuration values.
    ac_chan_get_config_defaults(&config_ac_chan);
  10. Alter the channel configuration parameters to set the channel to one-shot mode, with the correct negative and positive MUX selections and the desired voltage scaler.
    Note
    The voltage scalar formula is documented in description for ac_chan_config::vcc_scale_factor.
  11. Select when the interrupt should occur. In this case an interrupt will occur at every finished conversion.
    config_ac_chan.sample_mode = AC_CHAN_MODE_SINGLE_SHOT;
    #if (SAMR30E)
    config_ac_chan.positive_input = AC_CHAN_POS_MUX_PIN2;
    #else
    config_ac_chan.positive_input = AC_CHAN_POS_MUX_PIN0;
    #endif
    config_ac_chan.negative_input = AC_CHAN_NEG_MUX_SCALED_VCC;
    config_ac_chan.vcc_scale_factor = 32;
    config_ac_chan.interrupt_selection = AC_CHAN_INTERRUPT_SELECTION_END_OF_COMPARE;
  12. Configure the physical pin that will be routed to the AC module channel 0.
    struct system_pinmux_config ac0_pin_conf;
    ac0_pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
    ac0_pin_conf.mux_position = CONF_AC_MUX;
    system_pinmux_pin_set_config(CONF_AC_PIN, &ac0_pin_conf);
  13. Initialize the Analog Comparator channel and configure it with the desired settings.
  14. Enable the initialized Analog Comparator channel.
  15. Create a new callback function.
    void callback_function_ac(struct ac_module *const module_inst)
    {
    }
  16. Create a callback status software flag.
    bool volatile callback_status = false;
  17. Let the callback function set the calback_status flag to true.
    callback_status = true;
  18. Create a new function configure_ac_callback(), which will be used to configure the callbacks.
  19. Register callback function.
  20. Enable the callbacks.
  21. Enable the now initialized Analog Comparator peripheral.
    Note
    This should not be done until after the AC is setup and ready to be used.

Implementation

Code

Copy-paste the following code to your user application:

uint8_t last_comparison = AC_CHAN_STATUS_UNKNOWN;
port_pin_set_output_level(LED_0_PIN, true);
while (true) {
if (callback_status == true) {
do
{
last_comparison = ac_chan_get_status(&ac_instance,
} while (last_comparison & AC_CHAN_STATUS_UNKNOWN);
(last_comparison & AC_CHAN_STATUS_NEG_ABOVE_POS));
callback_status = false;
}
}

Workflow

  1. Trigger the first comparison on the comparator channel.
  2. Create a local variable to maintain the current comparator state. Since no comparison has taken place, it is initialized to AC_CHAN_STATUS_UNKNOWN.
    uint8_t last_comparison = AC_CHAN_STATUS_UNKNOWN;
  3. Make the application loop infinitely, while performing triggered comparisons.
    while (true) {
  4. Check if a new comparison is complete.
    if (callback_status == true) {
  5. Check if the comparator is ready for the last triggered comparison result to be read.
    do
    {
    last_comparison = ac_chan_get_status(&ac_instance,
    } while (last_comparison & AC_CHAN_STATUS_UNKNOWN);
  6. Read the comparator output state into the local variable for application use, re-trying until the comparison state is ready.
    do
    {
    last_comparison = ac_chan_get_status(&ac_instance,
    } while (last_comparison & AC_CHAN_STATUS_UNKNOWN);
  7. Set the board LED state to mirror the last comparison state.
    (last_comparison & AC_CHAN_STATUS_NEG_ABOVE_POS));
  8. After the interrupt is handled, set the software callback flag to false.
    callback_status = false;
  9. Trigger the next conversion on the Analog Comparator channel.