/* ---------------------------------------------------------------------------- * ATMEL Microcontroller Software Support * ---------------------------------------------------------------------------- * Copyright (c) 2009, Atmel Corporation * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the disclaimer below. * * Atmel's name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: 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 * 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. * ---------------------------------------------------------------------------- */ /** \addtogroup adc_module Working with ADC * The ADC driver provides the interface to configure and use the ADC peripheral. * \n * * It converts the analog input to digital format. The converted result could be * 12bit or 10bit. The ADC supports up to 16 analog lines. * * To Enable a ADC conversion,the user has to follow these few steps: * * * For more accurate information, please look at the ADC section of the * Datasheet. * * Related files :\n * \ref adc.c\n * \ref adc.h\n */ /*---------------------------------------------------------------------------- * Headers *----------------------------------------------------------------------------*/ #include #include #include /*---------------------------------------------------------------------------- * Exported functions *----------------------------------------------------------------------------*/ /** * \brief Initialize the ADC controller * \param pAdc Pointer to an Adc instance. * \param trgEn trigger mode, software or Hardware * \param trgSel hardware trigger selection * \param sleepMode sleep mode selection * \param resolution resolution selection 10 bits or 12 bits * \param mckClock value of MCK in Hz * \param adcClock value of the ADC clock in Hz * \param startupTime value of the start up time (in ADCClock) (see datasheet) * \param trackingt Tracking Time (in ADCClock cycle) */ void ADC_Initialize(Adc *pAdc, uint8_t idAdc, uint8_t trgEn, uint8_t trgSel, uint8_t sleepMode, uint8_t resolution, uint32_t mckClock, uint32_t adcClock, uint32_t startup, uint32_t tracking) { uint32_t prescal; prescal = (mckClock / (2*adcClock)) - 1; ASSERT( (prescal<0x3F), "ADC Bad PRESCAL\n\r"); TRACE_DEBUG("adcClock:%lu MasterClock:%lu\n\r", (mckClock/((prescal+1)*2)), mckClock); if( adcClock != (mckClock/((prescal+1)*2)) ) { TRACE_WARNING("User and calculated adcClocks are different : " "user=%lu calc=%lu\n\r", adcClock, (mckClock/((prescal+1)*2))); } /* Enable peripheral clock*/ PMC->PMC_PCER0 = 1 << idAdc; /* Reset the controller */ ADC_SoftReset(pAdc); /* Write to the MR register */ ADC_CfgModeReg( pAdc, ( trgEn & ADC_MR_TRGEN) | ( trgSel & ADC_MR_TRGSEL) | ( resolution & ADC_MR_LOWRES) | ( sleepMode & ADC_MR_SLEEP) | ( (prescal<<8) & ADC_MR_PRESCAL) | ( (startup<<16) & ADC_MR_STARTUP) | ( (tracking<<24) & ADC_MR_TRACKTIM) ); } /** * Return the Channel Converted Data * \param pAdc Pointer to an Adc instance. * \param channel channel to get converted value */ uint32_t ADC_GetConvertedData(Adc *pAdc, uint32_t channel) { uint32_t data=0; if (15 >= channel) { data = *((RoReg *)((uint32_t)&(pAdc->ADC_CDR0)+ channel*4)); } return data; } /** * Set compare channel * \param pAdc Pointer to an Adc instance. * \param channel channel number to be set,16 for all channels */ void ADC_SetCompareChannel(Adc *pAdc, uint8_t channel) { ASSERT(channel<=16, "Invalid channel number"); if (channel < 16) { pAdc->ADC_EMR &= ~(ADC_EMR_CMPALL); pAdc->ADC_EMR &= ~(ADC_EMR_CMPSEL); pAdc->ADC_EMR |= (channel << 4); } else { pAdc->ADC_EMR |= ADC_EMR_CMPALL; } } /** * Set compare mode * \param pAdc Pointer to an Adc instance. * \param mode compare mode */ void ADC_SetCompareMode(Adc *pAdc, uint8_t mode) { pAdc->ADC_EMR &= ~(ADC_EMR_CMPMODE); pAdc->ADC_EMR |= mode; } /** * Set comparsion window,one thereshold each time * \param pAdc Pointer to an Adc instance. * \param hi_lo Comparison Window */ void ADC_SetComparisonWindow(Adc *pAdc, uint32_t hi_lo) { pAdc->ADC_CWR = hi_lo; } /**---------------------------------------------------------------------------- * Test if ADC Interrupt is Masked * \param pAdc Pointer to an Adc instance. * \param flag flag to be tested * \return 1 if interrupt is masked, otherwise 0 */ uint32_t ADC_IsInterruptMasked(Adc *pAdc, uint32_t flag) { return (ADC_GetInterruptMaskStatus(pAdc) & flag); } /**---------------------------------------------------------------------------- * Test if ADC Status is Set * \param pAdc Pointer to an Adc instance. * \param flag flag to be tested * \return 1 if the staus is set; 0 otherwise */ uint32_t ADC_IsStatusSet(Adc *pAdc, uint32_t flag) { return (ADC_GetStatus(pAdc) & flag); } /**---------------------------------------------------------------------------- * Test if ADC channel interrupt Status is Set * \param adc_sr Value of SR register * \param channel Channel to be tested * \return 1 if interrupt status is set, otherwise 0 */ uint8_t ADC_IsChannelInterruptStatusSet(uint32_t adc_sr, uint32_t channel) { uint8_t status; if((adc_sr & (1<ADC_RCR == 0) && (pADC->ADC_RNCR == 0)) { pADC->ADC_RPR = (uint32_t) pBuffer; pADC->ADC_RCR = size; pADC->ADC_PTCR = ADC_PTCR_RXTEN; return 1; } /* Check if the second PDC bank is free*/ else if (pADC->ADC_RNCR == 0) { pADC->ADC_RNPR = (uint32_t) pBuffer; pADC->ADC_RNCR = size; return 1; } else { return 0; } }