Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
targets/TARGET_Atmel/TARGET_SAM_CortexM4/drivers/adc/adc2.h
- Committer:
- WaleedElmughrabi
- Date:
- 2018-09-20
- Revision:
- 188:60408c49b6d4
- Parent:
- 149:156823d33999
File content as of revision 188:60408c49b6d4:
/** * \file * * \brief ADC Controller driver. * * Copyright (c) 2013-2015 Atmel Corporation. All rights reserved. * * \asf_license_start * * \page License * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The name of Atmel may not be used to endorse or promote products derived * from this software without specific prior written permission. * * 4. This software may only be redistributed and used in connection with an * Atmel microcontroller product. * * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * \asf_license_stop * */ /* * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> */ #ifndef ADC2_H_INCLUDED #define ADC2_H_INCLUDED #include "compiler.h" #include "status_codes.h" #if (SAM4N) #define TEMP_SENSOR #define SLEEP_MODE_ADC SLEEPMGR_SLEEP_WFI #endif #if (SAMG) #define NO_TEMP_SENSOR #define SLEEP_MODE_ADC SLEEPMGR_ACTIVE #endif /** Write Protect Key */ #ifndef ADC_WPMR_WPKEY_PASSWD #define ADC_WPMR_WPKEY_PASSWD (0x414443u << 8) #endif /** Definitions for ADC resolution */ enum adc_resolution { #if SAMG55 ADC_12_BITS = ADC_EMR_OSR_NO_AVERAGE, /* ADC 12-bit resolution */ ADC_13_BITS = ADC_EMR_OSR_OSR4, /* ADC 13-bit resolution */ ADC_14_BITS = ADC_EMR_OSR_OSR16, /* ADC 14-bit resolution */ ADC_15_BITS = ADC_EMR_OSR_OSR64, /* ADC 15-bit resolution */ ADC_16_BITS = ADC_EMR_OSR_OSR256, /* ADC 16-bit resolution */ #else ADC_8_BITS = ADC_MR_LOWRES_BITS_8, /* ADC 8-bit resolution */ ADC_10_BITS = ADC_MR_LOWRES_BITS_10, /* ADC 10-bit resolution */ ADC_11_BITS = ADC_EMR_OSR_OSR4, /* ADC 11-bit resolution */ ADC_12_BITS = ADC_EMR_OSR_OSR16 /* ADC 12-bit resolution */ #endif }; /** Definitions for ADC power mode */ enum adc_power_mode { /* ADC core on and reference voltage circuitry on */ ADC_POWER_MODE_0 = 0, /* ADC core off and reference voltage circuitry off */ ADC_POWER_MODE_1 }; /** Definitions for ADC trigger */ enum adc_trigger { /* Starting a conversion is only possible by software. */ ADC_TRIG_SW = ADC_MR_TRGEN_DIS, /* External trigger */ ADC_TRIG_EXT = ADC_MR_TRGSEL_ADC_TRIG0 | ADC_MR_TRGEN, /* TIO Output of the Timer Counter Channel 0 */ ADC_TRIG_TIO_CH_0 = ADC_MR_TRGSEL_ADC_TRIG1 | ADC_MR_TRGEN, /* TIO Output of the Timer Counter Channel 1 */ ADC_TRIG_TIO_CH_1 = ADC_MR_TRGSEL_ADC_TRIG2 | ADC_MR_TRGEN, /* TIO Output of the Timer Counter Channel 2 */ ADC_TRIG_TIO_CH_2 = ADC_MR_TRGSEL_ADC_TRIG3 | ADC_MR_TRGEN, #if (SAMG) /* RTCOUT0 */ ADC_TRIG_RTC_0 = ADC_MR_TRGSEL_ADC_TRIG4 | ADC_MR_TRGEN, /* RTTINC */ ADC_TRIG_RTT = ADC_MR_TRGSEL_ADC_TRIG5 | ADC_MR_TRGEN, #endif /* Freerun mode conversion. */ ADC_TRIG_FREERUN = 0xFF }; /** Definitions for ADC channel number */ enum adc_channel_num { ADC_CHANNEL_0 = 0, ADC_CHANNEL_1, ADC_CHANNEL_2, ADC_CHANNEL_3, ADC_CHANNEL_4, ADC_CHANNEL_5, ADC_CHANNEL_6, ADC_CHANNEL_7, #if (SAM4N) ADC_CHANNEL_8, ADC_CHANNEL_9, ADC_CHANNEL_10, ADC_CHANNEL_11, ADC_CHANNEL_12, ADC_CHANNEL_13, ADC_CHANNEL_14, ADC_CHANNEL_15, #endif #ifdef TEMP_SENSOR ADC_TEMPERATURE_SENSOR, #endif ADC_CHANNEL_ALL = 0xFFFF }; /** Definitions for ADC Start Up Time */ enum adc_startup_time { ADC_STARTUP_TIME_0 = ADC_MR_STARTUP_SUT0, ADC_STARTUP_TIME_1 = ADC_MR_STARTUP_SUT8, ADC_STARTUP_TIME_2 = ADC_MR_STARTUP_SUT16, ADC_STARTUP_TIME_3 = ADC_MR_STARTUP_SUT24, ADC_STARTUP_TIME_4 = ADC_MR_STARTUP_SUT64, ADC_STARTUP_TIME_5 = ADC_MR_STARTUP_SUT80, ADC_STARTUP_TIME_6 = ADC_MR_STARTUP_SUT96, ADC_STARTUP_TIME_7 = ADC_MR_STARTUP_SUT112, ADC_STARTUP_TIME_8 = ADC_MR_STARTUP_SUT512, ADC_STARTUP_TIME_9 = ADC_MR_STARTUP_SUT576, ADC_STARTUP_TIME_10 = ADC_MR_STARTUP_SUT640, ADC_STARTUP_TIME_11 = ADC_MR_STARTUP_SUT704, ADC_STARTUP_TIME_12 = ADC_MR_STARTUP_SUT768, ADC_STARTUP_TIME_13 = ADC_MR_STARTUP_SUT832, ADC_STARTUP_TIME_14 = ADC_MR_STARTUP_SUT896, ADC_STARTUP_TIME_15 = ADC_MR_STARTUP_SUT960 }; /** Definitions for Comparison Mode */ enum adc_cmp_mode { ADC_CMP_MODE_0 = ADC_EMR_CMPMODE_LOW, ADC_CMP_MODE_1 = ADC_EMR_CMPMODE_HIGH, ADC_CMP_MODE_2 = ADC_EMR_CMPMODE_IN, ADC_CMP_MODE_3 = ADC_EMR_CMPMODE_OUT }; #ifdef TEMP_SENSOR /** Definitions for Temperature Comparison Mode */ enum adc_temp_cmp_mode { ADC_TEMP_CMP_MODE_0 = ADC_TEMPMR_TEMPCMPMOD_LOW, ADC_TEMP_CMP_MODE_1 = ADC_TEMPMR_TEMPCMPMOD_HIGH, ADC_TEMP_CMP_MODE_2 = ADC_TEMPMR_TEMPCMPMOD_IN, ADC_TEMP_CMP_MODE_3 = ADC_TEMPMR_TEMPCMPMOD_OUT }; #endif #if (SAMG) /** Definitions for Last Channel Specific Measurement Comparison Mode */ enum adc_last_channel_cmp_mode { ADC_LAST_CHANNEL_CMP_MODE_0 = ADC_LCTMR_CMPMOD_LOW, ADC_LAST_CHANNEL_CMP_MODE_1 = ADC_LCTMR_CMPMOD_HIGH, ADC_LAST_CHANNEL_CMP_MODE_2 = ADC_LCTMR_CMPMOD_IN, ADC_LAST_CHANNEL_CMP_MODE_3 = ADC_LCTMR_CMPMOD_OUT }; #endif /** Definitions for Reference Voltage Selection */ enum adc_refer_voltage_source { ADC_REFER_VOL_EXTERNAL = 0, ADC_REFER_VOL_STUCK_AT_MIN, ADC_REFER_VOL_VDDANA, ADC_REFER_VOL_IRVS }; /** * \brief ADC Enhanced configuration structure. * * Configuration structure for a ADC Enhanced instance. * This structure could be initialized by the \ref ADC_get_config_defaults() * function before being modified by the user application. */ struct adc_config { /** Resolution */ enum adc_resolution resolution; /** Master Clock */ uint32_t mck; /** ADC Clock */ uint32_t adc_clock; /** Start Up Time */ enum adc_startup_time startup_time; /** Tracking Time = (tracktim+1) / ADC clock */ uint8_t tracktim; /** Transfer Period */ uint8_t transfer; /** Use Sequence Enable */ bool useq; /** TAG of ADC_LDCR register */ bool tag; /** Averaging on Single Trigger Event */ bool aste; }; #ifdef TEMP_SENSOR /** ADC Temperature Sensor configuration structure.*/ struct adc_temp_sensor_config { /** Temperature Sensor On */ bool tempon; /** Temperature Comparison Mode */ enum adc_temp_cmp_mode mode; /** Temperature Low Threshold */ uint16_t low_threshold; /** Temperature High Threshold */ uint16_t high_threshold; }; #endif #if (SAMG) /** ADC Last Channel Specific Measurement configuration structure.*/ struct adc_last_channel_config { /** Specific Measurement On */ bool dual_trig_on; /** Specific Measurement Comparison Mode */ enum adc_last_channel_cmp_mode mode; /** Specific Measurement Low Threshold */ uint16_t low_threshold; /** Specific Measurement High Threshold */ uint16_t high_threshold; }; #endif /** ADC interrupt source type */ enum adc_interrupt_source { ADC_INTERRUPT_EOC_0 = 0, ADC_INTERRUPT_EOC_1, ADC_INTERRUPT_EOC_2, ADC_INTERRUPT_EOC_3, ADC_INTERRUPT_EOC_4, ADC_INTERRUPT_EOC_5, ADC_INTERRUPT_EOC_6, ADC_INTERRUPT_EOC_7, #if (SAM4N) ADC_INTERRUPT_EOC_8, ADC_INTERRUPT_EOC_9, ADC_INTERRUPT_EOC_10, ADC_INTERRUPT_EOC_11, ADC_INTERRUPT_EOC_12, ADC_INTERRUPT_EOC_13, ADC_INTERRUPT_EOC_14, ADC_INTERRUPT_EOC_15, ADC_INTERRUPT_EOC_16, #endif #ifdef TEMP_SENSOR ADC_INTERRUPT_TEMP_CHANGE, #endif ADC_INTERRUPT_END_CAL, ADC_INTERRUPT_DATA_READY, ADC_INTERRUPT_OVERRUN_ERROR, ADC_INTERRUPT_COMP_ERROR, ADC_INTERRUPT_END_RXBUF, ADC_INTERRUPT_RXBUF_FULL, ADC_INTERRUPT_ALL = 0xFFFFFFFF }; typedef void (*adc_callback_t)(void); void adc_get_config_defaults(struct adc_config *const cfg); enum status_code adc_init(Adc *const adc, struct adc_config *const config); #ifdef TEMP_SENSOR void adc_temp_sensor_get_config_defaults( struct adc_temp_sensor_config *const cfg); void adc_temp_sensor_set_config(Adc *const adc, struct adc_temp_sensor_config *config); #endif #if (SAMG) void adc_last_channel_get_config_defaults( struct adc_last_channel_config *const cfg); void adc_last_channel_set_config(Adc *const adc, struct adc_last_channel_config *config); #endif void adc_configure_sequence(Adc *const adc, const enum adc_channel_num ch_list[], const uint8_t uc_num); void adc_enable(void); void adc_disable(void); void adc_set_callback(Adc *const adc, enum adc_interrupt_source source, adc_callback_t callback, uint8_t irq_level); /** * \internal * \brief ADC channel sanity check * * \param adc Base address of the ADC. * \param channel Adc channel number. * */ static inline void adc_ch_sanity_check(Adc *const adc, const enum adc_channel_num channel) { if (adc == ADC) { Assert((channel < NB_CH_ADC) #ifdef TEMP_SENSOR ||(channel == ADC_TEMPERATURE_SENSOR) #endif ); } UNUSED(channel); } #if (SAMG) #if SAMG55 /** * \brief Configure ADC clock to mck. * * \param adc Base address of the ADC. * */ static inline void adc_select_clock_source_mck(Adc *const adc) { uint32_t reg; reg = adc->ADC_EMR; reg &= ~ADC_EMR_SRCCLK_PMC_PCK; adc->ADC_EMR = reg; } /** * \brief Configure ADC clock to pck. * * \param adc Base address of the ADC. * */ static inline void adc_select_clock_source_pck(Adc *const adc) { uint32_t reg; reg = adc->ADC_EMR; reg |= ADC_EMR_SRCCLK_PMC_PCK; adc->ADC_EMR = reg; } #else /** * \brief Configure ADC clock to MCK. * * \param adc Base address of the ADC. * */ static inline void adc_set_clock_mck(Adc *const adc) { uint32_t reg; reg = adc->ADC_EMR; reg |= ADC_MR_DIV1; adc->ADC_MR = reg; } /** * \brief Configure ADC clock to MCK/3. * * \param adc Base address of the ADC. * */ static inline void adc_set_clock_mck_div3(Adc *const adc) { uint32_t reg; reg = adc->ADC_MR; reg &= ~ADC_MR_DIV1; reg |= ADC_MR_DIV3; adc->ADC_MR = reg; } #endif #endif /** * \brief Configure conversion trigger and free run mode. * * \param adc Base address of the ADC. * \param trigger Conversion trigger. * */ static inline void adc_set_trigger(Adc *const adc, const enum adc_trigger trigger) { uint32_t reg; reg = adc->ADC_MR; if (trigger == ADC_TRIG_FREERUN) { reg |= ADC_MR_FREERUN_ON; } else { reg &= ~(ADC_MR_TRGSEL_Msk | ADC_MR_TRGEN | ADC_MR_FREERUN_ON); reg |= trigger; } adc->ADC_MR = reg; } void adc_set_resolution(Adc *const adc, const enum adc_resolution res); void adc_set_comparison_mode(Adc *const adc, const enum adc_cmp_mode mode, const enum adc_channel_num channel, uint8_t cmp_filter); /** * \brief Get comparison mode. * * \param adc Base address of the ADC. * * \retval Compare mode value. */ static inline enum adc_cmp_mode adc_get_comparison_mode(Adc *const adc) { return (enum adc_cmp_mode)(adc->ADC_EMR & ADC_EMR_CMPMODE_Msk); } /** * \brief Configure ADC compare window. * * \param adc Base address of the ADC. * \param us_low_threshold Low threshold of compare window. * \param us_high_threshold High threshold of compare window. */ static inline void adc_set_comparison_window(Adc *const adc, const uint16_t us_low_threshold, const uint16_t us_high_threshold) { adc->ADC_CWR = ADC_CWR_LOWTHRES(us_low_threshold) | ADC_CWR_HIGHTHRES(us_high_threshold); } /** * \brief Enable or disable write protection of ADC registers. * * \param adc Base address of the ADC. * \param is_enable 1 to enable, 0 to disable. */ static inline void adc_set_writeprotect(Adc *const adc, const bool is_enable) { if (is_enable) { adc->ADC_WPMR = ADC_WPMR_WPEN | ADC_WPMR_WPKEY_PASSWD; } else { adc->ADC_WPMR = ADC_WPMR_WPKEY_PASSWD; } } /** * \brief Indicate write protect status. * * \param adc Base address of the ADC. * * \return 0 if no write protect violation occurred, or 16-bit write protect * violation source. */ static inline uint32_t adc_get_writeprotect_status(Adc *const adc) { uint32_t reg_value; reg_value = adc->ADC_WPSR; if (reg_value & ADC_WPSR_WPVS) { return (reg_value & ADC_WPSR_WPVSRC_Msk) >> ADC_WPSR_WPVSRC_Pos; } else { return 0; } } /** * \brief Get ADC overrun error status. * * \param adc Base address of the ADC. * * \return ADC overrun error status. */ static inline uint32_t adc_get_overrun_status(Adc *const adc) { return adc->ADC_OVER; } /** * \brief Set ADC averaging on single trigger event * * \param adc Base address of the ADC. */ static inline void adc_average_on_single_trigger(Adc *const adc) { adc->ADC_EMR |= ADC_EMR_ASTE_SINGLE_TRIG_AVERAGE; } /** * \brief Set ADC averaging on serval trigger events * * \param adc Base address of the ADC. */ static inline void adc_average_on_multi_trigger(Adc *const adc) { adc->ADC_EMR &= ~ADC_EMR_ASTE_SINGLE_TRIG_AVERAGE; } /** * \brief Start analog-to-digital conversion. * * \note If one of the hardware event is selected as ADC trigger, * this function can NOT start analog to digital conversion. * * \param adc Base address of the ADC. */ static inline void adc_start_software_conversion(Adc *const adc) { adc->ADC_CR = ADC_CR_START; } void adc_set_power_mode(Adc *const adc, const enum adc_power_mode mode); /** * \brief Enable the specified ADC channel. * * \param adc Base address of the ADC. * \param adc_ch Adc channel number. */ static inline void adc_channel_enable(Adc *const adc, const enum adc_channel_num adc_ch) { if (adc_ch != ADC_CHANNEL_ALL) { adc_ch_sanity_check(adc, adc_ch); } adc->ADC_CHER = (adc_ch == ADC_CHANNEL_ALL) ? ADC_CHANNEL_ALL : 1 << adc_ch; } /** * \brief Disable the specified ADC channel. * * \param adc Base address of the ADC. * \param adc_ch Adc channel number. */ static inline void adc_channel_disable(Adc *const adc, const enum adc_channel_num adc_ch) { if (adc_ch != ADC_CHANNEL_ALL) { adc_ch_sanity_check(adc, adc_ch); } adc->ADC_CHDR = (adc_ch == ADC_CHANNEL_ALL) ? ADC_CHANNEL_ALL : 1 << adc_ch; } /** * \brief Get the ADC channel status. * * \param adc Base address of the ADC. * \param adc_ch Adc channel number. * * \retval 1 if channel is enabled. * \retval 0 if channel is disabled. */ static inline uint32_t adc_channel_get_status(Adc *const adc, const enum adc_channel_num adc_ch) { adc_ch_sanity_check(adc, adc_ch); return adc->ADC_CHSR & (1 << adc_ch); } /** * \brief Read the Converted Data of the selected channel. * * \param adc Base address of the ADC. * \param adc_ch Adc channel number. * * \return ADC converted value of the selected channel. */ static inline uint32_t adc_channel_get_value(Adc *const adc, enum adc_channel_num adc_ch) { adc_ch_sanity_check(adc, adc_ch); return adc->ADC_CDR[adc_ch]; } /** * \brief Get the Last Data Converted. * * \param adc Base address of the ADC. * * \return ADC latest converted value. */ static inline uint32_t adc_get_latest_value(Adc *const adc) { return adc->ADC_LCDR & ADC_LCDR_LDATA_Msk; } /** * \brief Get the Last Converted Channel Number. * * \param adc Base address of the ADC. * * \return ADC Last Converted Channel Number. */ static inline uint32_t adc_get_latest_chan_num(Adc *const adc) { #if SAMG55 return (adc->ADC_LCDR & ADC_LCDR_CHNBOSR_Msk) >> ADC_LCDR_CHNBOSR_Pos; #else return (adc->ADC_LCDR & ADC_LCDR_CHNB_Msk) >> ADC_LCDR_CHNB_Pos; #endif } void adc_enable_interrupt(Adc *const adc, enum adc_interrupt_source interrupt_source); void adc_disable_interrupt(Adc *const adc, enum adc_interrupt_source interrupt_source); /** * \brief Get ADC interrupt status. * * \param adc Base address of the ADC. * * \return The interrupt status value. */ static inline uint32_t adc_get_interrupt_status(Adc *const adc) { return adc->ADC_ISR; } /** * \brief Get ADC interrupt mask. * * \param adc Base address of the ADC. * * \return The interrupt mask value. */ static inline uint32_t adc_get_interrupt_mask(Adc *const adc) { return adc->ADC_IMR; } /** * \brief Get PDC registers base address. * * \param adc Base address of the ADC. * * \return Adc Pdc register base address. */ static inline Pdc *adc_get_pdc_base(Adc *const adc) { Pdc *p_pdc_base = NULL; if (adc == ADC) { p_pdc_base = PDC_ADC; } return p_pdc_base; } /** * \brief Launch an automatic calibration of the ADC on next sequence. * * \param adc Base address of the ADC. * * \retval STATUS_OK An automatic calibration is launched. * \retval STATUS_ERR_BUSY Automatic calibration can not be launched because * the ADC is in freerun mode. */ static inline enum status_code adc_start_calibration(Adc *const adc) { if ((adc->ADC_MR & ADC_MR_FREERUN) == ADC_MR_FREERUN_ON) { return STATUS_ERR_BUSY; } adc->ADC_CR = ADC_CR_AUTOCAL; return STATUS_OK; } #if (SAM4N) /** * \brief ADC Reference Voltage Selection * * \param adc Base address of the ADC. * \param adc_ref_src The source selection for ADC reference voltage, * ADC_REFER_VOL_EXTERNAL - the external pin ADVREF defines the voltage reference. * ADC_REFER_VOL_STUCK_AT_MIN - the internal reference voltage is stuck at the minimum value * ADC_REFER_VOL_VDDANA - the internal voltage reference is forced to VDDANA. Effective only if ONREF is 1. * ADC_REFER_VOL_IRVS - the internal reference voltage is defined by field IRVS * See the product electrical characteristics for further details. * \param irvs Internal reference volatage selection, only be effective when * adc_ref_src equals to ADC_REFER_VOL_IRVS */ static inline void adc_ref_vol_sel(Adc *const adc, enum adc_refer_voltage_source adc_ref_src, uint8_t irvs) { if (ADC_REFER_VOL_EXTERNAL == adc_ref_src) { adc->ADC_ACR &= ~ADC_ACR_ONREF_EN; } else if (ADC_REFER_VOL_STUCK_AT_MIN == adc_ref_src) { adc->ADC_ACR |= ADC_ACR_ONREF_EN; adc->ADC_ACR &= ~(ADC_ACR_IRVCE_EN | ADC_ACR_FORCEREF_EN); } else if (ADC_REFER_VOL_VDDANA == adc_ref_src) { adc->ADC_ACR |= ADC_ACR_ONREF_EN | ADC_ACR_FORCEREF_EN; } else if (ADC_REFER_VOL_IRVS == adc_ref_src) { adc->ADC_ACR &= ~ADC_ACR_FORCEREF_EN; adc->ADC_ACR |= ADC_ACR_ONREF_EN | ADC_ACR_IRVCE_EN | (irvs << ADC_ACR_IRVS_Pos); } } #endif /** * \page sam_adc2_quickstart Quickstart guide for ADC driver * * This is the quickstart guide for the \ref sam_drivers_adc2_group * "ADC2 driver" with step-by-step instructions on how to configure and use * the driver in a selection of use cases. * * The use cases contain several code fragments. The code fragments in the * steps for setup can be copied into a custom initialization function, while * the steps for usage can be copied into, e.g., the main application function. * * \section adc_basic_use_case Basic use case * In this basic use case, the ADC module and single channel are configured for: * - 10 -bit resolution * - ADC clock frequency is 6MHz * - Start Up Time is 64 periods ADC clock * - Tracking Time is 3 periods of ADC clock * - Transfer Period field shall be programmed with 2 as datasheet said * - The controller converts channels in a simple numeric order * - Appends the channel number to the conversion result in AFE_LDCR register * - Single Trigger is optional to get an averaged value * - Software triggering of conversions * - Single channel measurement * - ADC_CHANNEL_1 of ADC as input * * \subsection sam_adc2_quickstart_prereq Prerequisites * -# \ref sysclk_group "System Clock Management (Sysclock)" * * \section adc_basic_use_case_setup Setup steps * \subsection adc_basic_use_case_setup_code Example code * Add to application C-file: * \code adc_enable(); adc_get_config_defaults(&adc_cfg); adc_init(ADC, &adc_cfg); adc_set_trigger(ADC, ADC_TRIG_SW); adc_channel_enable(ADC, ADC_CHANNEL_1); \endcode * * \subsection adc_basic_use_case_setup_flow Workflow * -# Enable ADC Module: * - \code adc_enable(); \endcode * -# Get the ADC default configurations: * - \code adc_get_config_defaults(&adc_cfg); \endcode * -# Initialize the ADC Module: * - \code adc_init(ADC, &adc_cfg); \endcode * -# Configure conversion trigger and free run mode: * - \code adc_set_trigger(ADC, ADC_TRIG_SW); \endcode * -# Enable Channel: * - \code adc_channel_enable(ADC, ADC_CHANNEL_1); \endcode * * \section adc_basic_use_case_usage Usage steps * \subsection adc_basic_use_case_usage_code Example code * Add to, e.g., main loop in application C-file: * \code adc_start_software_conversion(ADC); while (adc_get_interrupt_status(ADC) & (1 << ADC_CHANNEL_1)); uint32_t result = adc_channel_get_value(ADC, ADC_CHANNEL_1); \endcode * * \subsection adc_basic_use_case_usage_flow Workflow * -# Start ADC conversion on channel: * - \code adc_start_software_conversion(ADC); \endcode * -# Wait for the conversion over: * - \code while (adc_get_interrupt_status(ADC) & (1 << ADC_CHANNEL_1)); \endcode * -# Get the conversion result: * - \code uint32_t result = adc_channel_get_value(ADC, ADC_CHANNEL_1); \endcode */ #endif /* ADC2_H_INCLUDED */