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.
analogin_api.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "analogin_api.h" 00017 00018 #if DEVICE_ANALOGIN 00019 00020 #include "cmsis.h" 00021 #include "pinmap.h" 00022 #include "error.h" 00023 00024 #define ANALOGIN_MEDIAN_FILTER 1 00025 00026 #define ADC_10BIT_RANGE 0x3FF 00027 #define ADC_12BIT_RANGE 0xFFF 00028 00029 static inline int div_round_up(int x, int y) { 00030 return (x + (y - 1)) / y; 00031 } 00032 00033 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00034 static const PinMap PinMap_ADC[] = { 00035 {P0_23, ADC0_0, 1}, 00036 {P0_24, ADC0_1, 1}, 00037 {P0_25, ADC0_2, 1}, 00038 {P0_26, ADC0_3, 1}, 00039 {P1_30, ADC0_4, 3}, 00040 {P1_31, ADC0_5, 3}, 00041 #ifdef TARGET_LPC1768 00042 {P0_2, ADC0_7, 2}, 00043 {P0_3, ADC0_6, 2}, 00044 #endif 00045 {NC, NC, 0} 00046 }; 00047 00048 #if defined(TARGET_LPC2368) 00049 # define ADC_RANGE ADC_10BIT_RANGE 00050 #elif defined(TARGET_LPC1768) 00051 # define ADC_RANGE ADC_12BIT_RANGE 00052 #endif 00053 00054 #elif defined(TARGET_LPC11U24) 00055 static const PinMap PinMap_ADC[] = { 00056 {P0_11, ADC0_0, 0x02}, 00057 {P0_12, ADC0_1, 0x02}, 00058 {P0_13, ADC0_2, 0x02}, 00059 {P0_14, ADC0_3, 0x02}, 00060 {P0_15, ADC0_4, 0x02}, 00061 {P0_16, ADC0_5, 0x01}, 00062 {P0_22, ADC0_6, 0x01}, 00063 {P0_23, ADC0_7, 0x01}, 00064 {NC , NC , 0 } 00065 }; 00066 00067 #define LPC_IOCON0_BASE (LPC_IOCON_BASE) 00068 #define LPC_IOCON1_BASE (LPC_IOCON_BASE + 0x60) 00069 00070 #define ADC_RANGE ADC_10BIT_RANGE 00071 #endif 00072 00073 void analogin_init(analogin_t *obj, PinName pin) { 00074 obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC); 00075 if (obj->adc == (uint32_t)NC) { 00076 error("ADC pin mapping failed"); 00077 } 00078 00079 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00080 // ensure power is turned on 00081 LPC_SC->PCONP |= (1 << 12); 00082 00083 // set PCLK of ADC to /1 00084 LPC_SC->PCLKSEL0 &= ~(0x3 << 24); 00085 LPC_SC->PCLKSEL0 |= (0x1 << 24); 00086 uint32_t PCLK = SystemCoreClock ; 00087 00088 // calculate minimum clock divider 00089 // clkdiv = divider - 1 00090 uint32_t MAX_ADC_CLK = 13000000; 00091 uint32_t clkdiv = div_round_up(PCLK, MAX_ADC_CLK) - 1; 00092 00093 // Set the generic software-controlled ADC settings 00094 LPC_ADC->ADCR = (0 << 0) // SEL: 0 = no channels selected 00095 | (clkdiv << 8) // CLKDIV: PCLK max ~= 25MHz, /25 to give safe 1MHz at fastest 00096 | (0 << 16) // BURST: 0 = software control 00097 | (0 << 17) // CLKS: not applicable 00098 | (1 << 21) // PDN: 1 = operational 00099 | (0 << 24) // START: 0 = no start 00100 | (0 << 27); // EDGE: not applicable 00101 00102 #elif defined(TARGET_LPC11U24) 00103 // Power up ADC 00104 LPC_SYSCON->PDRUNCFG &= ~ (1 << 4); 00105 LPC_SYSCON->SYSAHBCLKCTRL |= ((uint32_t)1 << 13); 00106 00107 uint32_t pin_number = (uint32_t)pin; 00108 __IO uint32_t *reg = (pin_number < 32) ? (__IO uint32_t*)(LPC_IOCON0_BASE + 4 * pin_number) : (__IO uint32_t*)(LPC_IOCON1_BASE + 4 * (pin_number - 32)); 00109 00110 // set pin to ADC mode 00111 *reg &= ~(1 << 7); // set ADMODE = 0 (analog mode) 00112 00113 uint32_t PCLK = SystemCoreClock ; 00114 uint32_t MAX_ADC_CLK = 4500000; 00115 uint32_t clkdiv = div_round_up(PCLK, MAX_ADC_CLK) - 1; 00116 00117 LPC_ADC->CR = (0 << 0) // no channels selected 00118 | (clkdiv << 8) // max of 4.5MHz 00119 | (0 << 16) // BURST = 0, software controlled 00120 | ( 0 << 17 ); // CLKS = 0, not applicable 00121 #endif 00122 pinmap_pinout(pin, PinMap_ADC); 00123 } 00124 00125 static inline uint32_t adc_read(analogin_t *obj) { 00126 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) 00127 // Select the appropriate channel and start conversion 00128 LPC_ADC->ADCR &= ~0xFF; 00129 LPC_ADC->ADCR |= 1 << (int)obj->adc; 00130 LPC_ADC->ADCR |= 1 << 24; 00131 00132 // Repeatedly get the sample data until DONE bit 00133 unsigned int data; 00134 do { 00135 data = LPC_ADC->ADGDR; 00136 } while ((data & ((unsigned int)1 << 31)) == 0); 00137 00138 // Stop conversion 00139 LPC_ADC->ADCR &= ~(1 << 24); 00140 00141 #elif defined(TARGET_LPC11U24) 00142 // Select the appropriate channel and start conversion 00143 LPC_ADC->CR &= ~0xFF; 00144 LPC_ADC->CR |= 1 << (int)obj->adc; 00145 LPC_ADC->CR |= 1 << 24; 00146 00147 // Repeatedly get the sample data until DONE bit 00148 unsigned int data; 00149 do { 00150 data = LPC_ADC->GDR; 00151 } while ((data & ((unsigned int)1 << 31)) == 0); 00152 00153 // Stop conversion 00154 LPC_ADC->CR &= ~(1 << 24); 00155 #endif 00156 00157 #if defined(TARGET_LPC1768) 00158 return (data >> 4) & ADC_RANGE; // 12 bit 00159 #elif defined(TARGET_LPC2368) || defined (TARGET_LPC11U24) 00160 return (data >> 6) & ADC_RANGE; // 10 bit 00161 #endif 00162 } 00163 00164 static inline void order(uint32_t *a, uint32_t *b) { 00165 if (*a > *b) { 00166 uint32_t t = *a; 00167 *a = *b; 00168 *b = t; 00169 } 00170 } 00171 00172 static inline uint32_t adc_read_u32(analogin_t *obj) { 00173 uint32_t value; 00174 #if ANALOGIN_MEDIAN_FILTER 00175 uint32_t v1 = adc_read(obj); 00176 uint32_t v2 = adc_read(obj); 00177 uint32_t v3 = adc_read(obj); 00178 order(&v1, &v2); 00179 order(&v2, &v3); 00180 order(&v1, &v2); 00181 value = v2; 00182 #else 00183 value = adc_read(obj); 00184 #endif 00185 return value; 00186 } 00187 00188 uint16_t analogin_read_u16(analogin_t *obj) { 00189 uint32_t value = adc_read_u32(obj); 00190 00191 #if defined(TARGET_LPC1768) 00192 return (value << 4) | ((value >> 8) & 0x000F); // 12 bit 00193 #elif defined(TARGET_LPC2368) || defined(TARGET_LPC11U24) 00194 return (value << 6) | ((value >> 4) & 0x003F); // 10 bit 00195 #endif 00196 } 00197 00198 float analogin_read(analogin_t *obj) { 00199 uint32_t value = adc_read_u32(obj); 00200 return (float)value * (1.0f / (float)ADC_RANGE); 00201 } 00202 00203 #endif
Generated on Thu Jul 14 2022 07:43:03 by
1.7.2