The supported board list:
- SAM D21 Xplained Pro
- SAM D11 Xplained Pro
- SAM L21 Xplained Pro
- SAM DA1 Xplained Pro
- SAM C21 Xplained Pro
- SAM HA1G16A Xplained Pro
This quick start will convert an analog input signal from AIN4 and output the converted value to DAC on PA2. The data between ADC and DAC with be transferred through DMA instead of a CPU intervene.
The ADC will be configured with the following settings:
- 1/2 VDDANA
- Div 16 clock prescaler
- 10-bit resolution
- Window monitor disabled
- No gain
- Positive input on ADC AIN4
- Averaging disabled
- Oversampling disabled
- Right adjust data
- Single-ended mode
- Free running enable
- All events (input and generation) disabled
- Sleep operation disabled
- No reference compensation
- No gain/offset correction
- No added sampling time
- Pin scan mode disabled
The DAC will be configured with the following settings:
- Analog VCC as reference
- Internal output disabled
- Drive the DAC output to PA2
- Right adjust data
- The output buffer is disabled when the chip enters STANDBY sleep mode
The DMA will be configured with the following settings:
- Move data from peripheral to peripheral
- Using ADC result ready trigger
- Using DMA priority level 0
- Beat transfer will be triggered on each trigger
- Loopback descriptor for DAC conversion
Setup
Prerequisites
There are no special setup requirements for this use-case.
Code
Add to the main application source file, outside of any functions:
Copy-paste the following setup code to your user application:
void configure_adc(void)
{
#if !(SAML21)
#if !(SAMC21)
config_adc.gain_factor = ADC_GAIN_FACTOR_DIV2;
#endif
#endif
config_adc.freerunning = true;
config_adc.left_adjust = false;
#if (SAMC21)
adc_init(&adc_instance, ADC1, &config_adc);
#else
adc_init(&adc_instance, ADC, &config_adc);
#endif
}
void configure_dac(void)
{
#if (SAML21)
#else
config_dac.reference = DAC_REFERENCE_AVCC;
#endif
dac_init(&dac_instance, DAC, &config_dac);
}
void configure_dac_channel(void)
{
}
{
#if (SAMC21)
config.peripheral_trigger = ADC1_DMAC_ID_RESRDY;
#else
config.peripheral_trigger = ADC_DMAC_ID_RESRDY;
#endif
}
void setup_transfer_descriptor(DmacDescriptor *descriptor)
{
descriptor_config.dst_increment_enable = false;
descriptor_config.src_increment_enable = false;
descriptor_config.block_transfer_count = 1000;
descriptor_config.source_address = (uint32_t)(&adc_instance.hw->RESULT.reg);
#if (SAML21)
descriptor_config.destination_address = (uint32_t)(&dac_instance.hw->DATA[
DAC_CHANNEL_0].reg);
#else
descriptor_config.destination_address = (uint32_t)(&dac_instance.hw->DATA.reg);
#endif
descriptor_config.next_descriptor_address = (uint32_t)descriptor;
}
Add to user application initialization (typically the start of main()
):
configure_adc();
configure_dac();
configure_dac_channel();
configure_dma_resource(&example_resource);
setup_transfer_descriptor(&example_descriptor);
Workflow
Configure the ADC
- Create a module software instance structure for the ADC module to store the ADC driver state while it is in use.
- Note
- This should never go out of scope as long as the module is in use. In most cases, this should be global.
- Configure the ADC module.
- Create an ADC module configuration struct, which can be filled out to adjust the configuration of a physical ADC peripheral.
- Initialize the ADC configuration struct with the module's default values.
- Note
- This should always be performed before using the configuration struct to ensure that all values are initialized to known default settings.
- Set extra configurations.
#if !(SAML21)
#if !(SAMC21)
config_adc.gain_factor = ADC_GAIN_FACTOR_DIV2;
#endif
#endif
config_adc.freerunning = true;
config_adc.left_adjust = false;
- Set ADC configurations.
#if (SAMC21)
adc_init(&adc_instance, ADC1, &config_adc);
#else
adc_init(&adc_instance, ADC, &config_adc);
#endif
- Enable the ADC module so that conversions can be made.
Configure the DAC
- Create a module software instance structure for the DAC module to store the DAC driver state while it is in use.
- Note
- This should never go out of scope as long as the module is in use. In most cases, this should be global.
- Configure the DAC module.
- Create a DAC module configuration struct, which can be filled out to adjust the configuration of a physical DAC peripheral.
- Initialize the DAC configuration struct with the module's default values.
- Note
- This should always be performed before using the configuration struct to ensure that all values are initialized to known default settings.
- Set extra DAC configurations.
#if (SAML21)
#else
config_dac.reference = DAC_REFERENCE_AVCC;
#endif
- Set DAC configurations to DAC instance.
dac_init(&dac_instance, DAC, &config_dac);
- Enable the DAC module so that channels can be configured.
- Configure the DAC channel.
- Create a DAC channel configuration struct, which can be filled out to adjust the configuration of a physical DAC output channel.
- Initialize the DAC channel configuration struct with the module's default values.
- Note
- This should always be performed before using the configuration struct to ensure that all values are initialized to known default settings.
- Configure the DAC channel with the desired channel settings.
- Enable the DAC channel so that it can output a voltage.
Configure the DMA
- Create a DMA resource configuration structure, which can be filled out to adjust the configuration of a single DMA transfer.
- Initialize the DMA resource configuration struct with the module's default values.
- Note
- This should always be performed before using the configuration struct to ensure that all values are initialized to known default settings.
- Set extra configurations for the DMA resource. ADC_DMAC_ID_RESRDY trigger causes a beat transfer in this example.
#if (SAMC21)
config.peripheral_trigger = ADC1_DMAC_ID_RESRDY;
#else
config.peripheral_trigger = ADC_DMAC_ID_RESRDY;
#endif
- Allocate a DMA resource with the configurations.
- Create a DMA transfer descriptor configuration structure, which can be filled out to adjust the configuration of a single DMA transfer.
- Initialize the DMA transfer descriptor configuration struct with the module's default values.
- Note
- This should always be performed before using the configuration struct to ensure that all values are initialized to known default settings.
- Set the specific parameters for a DMA transfer with transfer size, source address, and destination address.
descriptor_config.dst_increment_enable = false;
descriptor_config.src_increment_enable = false;
descriptor_config.block_transfer_count = 1000;
descriptor_config.source_address = (uint32_t)(&adc_instance.hw->RESULT.reg);
#if (SAML21)
descriptor_config.destination_address = (uint32_t)(&dac_instance.hw->DATA[
DAC_CHANNEL_0].reg);
#else
descriptor_config.destination_address = (uint32_t)(&dac_instance.hw->DATA.reg);
#endif
descriptor_config.next_descriptor_address = (uint32_t)descriptor;
- Create the DMA transfer descriptor.
- Add DMA descriptor to DMA resource.
Use Case
Code
Copy-paste the following code to your user application:
Workflow
- Start ADC conversion.
- Start the transfer job.
- Enter endless loop.