/********************************************************************** * $Id$ lpc43xx_adc.c 2011-06-02 *//** * @file lpc43xx_adc.c * @brief Contains all functions support for ADC firmware library on lpc43xx * @version 1.0 * @date 02. June. 2011 * @author NXP MCU SW Application Team * * Copyright(C) 2011, NXP Semiconductor * All rights reserved. * *********************************************************************** * Software that is described herein is for illustrative purposes only * which provides customers with programming information regarding the * products. This software is supplied "AS IS" without any warranties. * NXP Semiconductors assumes no responsibility or liability for the * use of the software, conveys no license or title under any patent, * copyright, or mask work right to the product. NXP Semiconductors * reserves the right to make changes in the software without * notification. NXP Semiconductors also make no representation or * warranty that such application will be suitable for the specified * use without further testing or modification. * Permission to use, copy, modify, and distribute this software and its * documentation is hereby granted, under NXP Semiconductors’ * relevant copyright in the software, without fee, provided that it * is used in conjunction with NXP Semiconductors microcontrollers. This * copyright, permission, and disclaimer notice must appear in all copies of * this code. **********************************************************************/ /* Peripheral group ----------------------------------------------------------- */ /** @addtogroup ADC * @{ */ /* Includes ------------------------------------------------------------------- */ #include "lpc43xx_adc.h" #include "lpc43xx_cgu.h" /* If this source file built with example, the lpc43xx FW library configuration * file in each example directory ("lpc43xx_libcfg.h") must be included, * otherwise the default FW library configuration file must be included instead */ #ifdef __BUILD_WITH_EXAMPLE__ #include "lpc43xx_libcfg.h" #else #include "lpc43xx_libcfg_default.h" #endif /* __BUILD_WITH_EXAMPLE__ */ #ifdef _ADC /* Public Functions ----------------------------------------------------------- */ /** @addtogroup ADC_Public_Functions * @{ */ /*********************************************************************//** * @brief Initial for ADC * + Set bit PCADC * + Set clock for ADC * + Set Clock Frequency * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @param[in] rate ADC conversion rate, should be <=200KHz * @param[in] bits_accuracy number of bits accuracy, should be <=10 bits and >=3bits * @return None **********************************************************************/ void ADC_Init(LPC_ADCn_Type *ADCx, uint32_t rate, uint8_t bits_accuracy) { uint32_t temp, tmpreg, ADCbitrate; CHECK_PARAM(PARAM_ADCx(ADCx)); CHECK_PARAM(PARAM_ADC_RATE(rate)); // Turn on power and clock //CGU_ConfigPPWR (CGU_PCONP_PCAD, ENABLE); ADCx->CR = 0; //Enable PDN bit tmpreg = ADC_CR_PDN; // Set clock frequency if(ADCx == LPC_ADC0) temp = CGU_GetPCLKFrequency(CGU_PERIPHERAL_ADC0); else if(ADCx == LPC_ADC1) temp = CGU_GetPCLKFrequency(CGU_PERIPHERAL_ADC1); /* The APB clock (PCLK_ADC0) is divided by (CLKDIV+1) to produce the clock for * A/D converter, which should be less than or equal to 13MHz. * A fully conversion requires (bits_accuracy+1) of these clocks. * ADC clock = PCLK_ADC0 / (CLKDIV + 1); * ADC rate = ADC clock / (bits_accuracy+1); */ ADCbitrate = (rate * (bits_accuracy+1)); temp = ((temp*2 + ADCbitrate) / (ADCbitrate*2)) - 1;//get the round value by fomular: (2*A + B)/(2*B) tmpreg |= ADC_CR_CLKDIV(temp) | ADC_CR_BITACC(10 - bits_accuracy); ADCx->CR = tmpreg; } /*********************************************************************//** * @brief Close ADC * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @return None **********************************************************************/ void ADC_DeInit(LPC_ADCn_Type *ADCx) { CHECK_PARAM(PARAM_ADCx(ADCx)); if (ADCx->CR & ADC_CR_START_MASK) //need to stop START bits before DeInit ADCx->CR &= ~ADC_CR_START_MASK; // Clear SEL bits ADCx->CR &= ~0xFF; // Clear PDN bit ADCx->CR &= ~ADC_CR_PDN; // Turn on power and clock //CGU_ConfigPPWR (CGU_PCONP_PCAD, DISABLE); } ///*********************************************************************//** //* @brief Get Result conversion from A/D data register //* @param[in] channel number which want to read back the result //* @return Result of conversion //*********************************************************************/ //uint32_t ADC_GetData(uint32_t channel) //{ // uint32_t adc_value; // // CHECK_PARAM(PARAM_ADC_CHANNEL_SELECTION(channel)); // // adc_value = *(uint32_t *)((&LPC_ADC->DR0) + channel); // return ADC_GDR_RESULT(adc_value); //} /*********************************************************************//** * @brief Set start mode for ADC * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @param[in] start_mode Start mode choose one of modes in * 'ADC_START_OPT' enumeration type definition, should be: * - ADC_START_CONTINUOUS * - ADC_START_NOW * - ADC_START_ON_EINT0 * - ADC_START_ON_CAP01 * - ADC_START_ON_MAT01 * - ADC_START_ON_MAT03 * - ADC_START_ON_MAT10 * - ADC_START_ON_MAT11 * @return None *********************************************************************/ void ADC_StartCmd(LPC_ADCn_Type *ADCx, uint8_t start_mode) { CHECK_PARAM(PARAM_ADCx(ADCx)); CHECK_PARAM(PARAM_ADC_START_OPT(start_mode)); ADCx->CR &= ~ADC_CR_START_MASK; ADCx->CR |=ADC_CR_START_MODE_SEL((uint32_t)start_mode); } /*********************************************************************//** * @brief ADC Burst mode setting * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @param[in] NewState * - 1: Set Burst mode * - 0: reset Burst mode * @return None **********************************************************************/ void ADC_BurstCmd(LPC_ADCn_Type *ADCx, FunctionalState NewState) { CHECK_PARAM(PARAM_ADCx(ADCx)); ADCx->CR &= ~ADC_CR_BURST; if (NewState){ ADCx->CR |= ADC_CR_BURST; } } /*********************************************************************//** * @brief Set AD conversion in power mode * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @param[in] NewState * - 1: AD converter is optional * - 0: AD Converter is in power down mode * @return None **********************************************************************/ void ADC_PowerdownCmd(LPC_ADCn_Type *ADCx, FunctionalState NewState) { CHECK_PARAM(PARAM_ADCx(ADCx)); ADCx->CR &= ~ADC_CR_PDN; if (NewState){ ADCx->CR |= ADC_CR_PDN; } } /*********************************************************************//** * @brief Set Edge start configuration * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @param[in] EdgeOption is ADC_START_ON_RISING and ADC_START_ON_FALLING * - 0: ADC_START_ON_RISING * - 1: ADC_START_ON_FALLING * @return None **********************************************************************/ void ADC_EdgeStartConfig(LPC_ADCn_Type *ADCx, uint8_t EdgeOption) { CHECK_PARAM(PARAM_ADCx(ADCx)); CHECK_PARAM(PARAM_ADC_START_ON_EDGE_OPT(EdgeOption)); ADCx->CR &= ~ADC_CR_EDGE; if (EdgeOption){ ADCx->CR |= ADC_CR_EDGE; } } /*********************************************************************//** * @brief ADC interrupt configuration * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @param[in] IntType: type of interrupt, should be: * - ADC_ADINTEN0: Interrupt channel 0 * - ADC_ADINTEN1: Interrupt channel 1 * ... * - ADC_ADINTEN7: Interrupt channel 7 * - ADC_ADGINTEN: Individual channel/global flag done generate an interrupt * @param[in] NewState: * - SET : enable ADC interrupt * - RESET: disable ADC interrupt * @return None **********************************************************************/ void ADC_IntConfig (LPC_ADCn_Type *ADCx, ADC_TYPE_INT_OPT IntType, FunctionalState NewState) { CHECK_PARAM(PARAM_ADCx(ADCx)); CHECK_PARAM(PARAM_ADC_TYPE_INT_OPT(IntType)); ADCx->INTEN &= ~ADC_INTEN_CH(IntType); if (NewState){ ADCx->INTEN |= ADC_INTEN_CH(IntType); } } /*********************************************************************//** * @brief Enable/Disable ADC channel number * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @param[in] Channel channel number * @param[in] NewState New state, should be: * - ENABLE * - DISABLE * @return None **********************************************************************/ void ADC_ChannelCmd (LPC_ADCn_Type *ADCx, uint8_t Channel, FunctionalState NewState) { CHECK_PARAM(PARAM_ADCx(ADCx)); CHECK_PARAM(PARAM_ADC_CHANNEL_SELECTION(Channel)); if (NewState == ENABLE) { ADCx->CR |= ADC_CR_CH_SEL(Channel); } else { if (ADCx->CR & ADC_CR_START_MASK) //need to stop START bits before disable channel ADCx->CR &= ~ADC_CR_START_MASK; ADCx->CR &= ~ADC_CR_CH_SEL(Channel); } } /*********************************************************************//** * @brief Get ADC result * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @param[in] channel channel number, should be 0...7 * @return Converted data **********************************************************************/ uint16_t ADC_ChannelGetData(LPC_ADCn_Type *ADCx, uint8_t channel) { uint32_t adc_value; CHECK_PARAM(PARAM_ADCx(ADCx)); CHECK_PARAM(PARAM_ADC_CHANNEL_SELECTION(channel)); adc_value = *(uint32_t *) ((&(ADCx->DR[0])) + channel); return ADC_DR_RESULT(adc_value); } /*********************************************************************//** * @brief Get ADC Channel status from ADC data register * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @param[in] channel: channel number, should be 0..7 * @param[in] StatusType * - 0: Burst status * - 1: Done status * @return Channel status, could be: * - SET * - RESET **********************************************************************/ FlagStatus ADC_ChannelGetStatus(LPC_ADCn_Type *ADCx, uint8_t channel, uint32_t StatusType) { uint32_t temp; CHECK_PARAM(PARAM_ADCx(ADCx)); CHECK_PARAM(PARAM_ADC_CHANNEL_SELECTION(channel)); CHECK_PARAM(PARAM_ADC_DATA_STATUS(StatusType)); temp = *(uint32_t *) ((&ADCx->DR[0]) + channel); if (StatusType) { temp &= ADC_DR_DONE_FLAG; }else{ temp &= ADC_DR_OVERRUN_FLAG; } if (temp) { return SET; } else { return RESET; } } /*********************************************************************//** * @brief Get ADC Data from AD Global register * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @return Result of conversion **********************************************************************/ uint32_t ADC_GlobalGetData(LPC_ADCn_Type *ADCx) { CHECK_PARAM(PARAM_ADCx(ADCx)); return ((uint32_t)(ADCx->GDR)); } /*********************************************************************//** * @brief Get ADC Chanel status from AD global data register * @param[in] ADCx pointer to LPC_ADCn_Type, should be: LPC_ADC * @param[in] StatusType * - 0: Burst status * - 1: Done status * @return SET / RESET **********************************************************************/ FlagStatus ADC_GlobalGetStatus(LPC_ADCn_Type *ADCx, uint32_t StatusType) { uint32_t temp; CHECK_PARAM(PARAM_ADCx(ADCx)); CHECK_PARAM(PARAM_ADC_DATA_STATUS(StatusType)); temp = ADCx->GDR; if (StatusType){ temp &= ADC_DR_DONE_FLAG; }else{ temp &= ADC_DR_OVERRUN_FLAG; } if (temp){ return SET; }else{ return RESET; } } /** * @} */ #endif /* _ADC */ /** * @} */ /* --------------------------------- End Of File ------------------------------ */