fix for mbed lib issue 3 (i2c problem) see also https://mbed.org/users/mbed_official/code/mbed/issues/3 affected implementations: LPC812, LPC11U24, LPC1768, LPC2368, LPC4088
Fork of mbed-src by
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 #include "cmsis.h" 00018 #include "pinmap.h" 00019 #include "error.h" 00020 00021 #define ANALOGIN_MEDIAN_FILTER 1 00022 00023 #define ADC_10BIT_RANGE 0x3FF 00024 #define ADC_12BIT_RANGE 0xFFF 00025 00026 static inline int div_round_up(int x, int y) { 00027 return (x + (y - 1)) / y; 00028 } 00029 00030 static const PinMap PinMap_ADC[] = { 00031 {P0_23, ADC0_0, 1}, 00032 {P0_24, ADC0_1, 1}, 00033 {P0_25, ADC0_2, 1}, 00034 {P0_26, ADC0_3, 1}, 00035 {P1_30, ADC0_4, 3}, 00036 {P1_31, ADC0_5, 3}, 00037 {NC, NC, 0} 00038 }; 00039 00040 #define ADC_RANGE ADC_10BIT_RANGE 00041 00042 00043 void analogin_init(analogin_t *obj, PinName pin) { 00044 obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC); 00045 if (obj->adc == (uint32_t)NC) { 00046 error("ADC pin mapping failed"); 00047 } 00048 00049 // ensure power is turned on 00050 LPC_SC->PCONP |= (1 << 12); 00051 00052 // set PCLK of ADC to /1 00053 LPC_SC->PCLKSEL0 &= ~(0x3 << 24); 00054 LPC_SC->PCLKSEL0 |= (0x1 << 24); 00055 uint32_t PCLK = SystemCoreClock; 00056 00057 // calculate minimum clock divider 00058 // clkdiv = divider - 1 00059 uint32_t MAX_ADC_CLK = 13000000; 00060 uint32_t clkdiv = div_round_up(PCLK, MAX_ADC_CLK) - 1; 00061 00062 // Set the generic software-controlled ADC settings 00063 LPC_ADC->ADCR = (0 << 0) // SEL: 0 = no channels selected 00064 | (clkdiv << 8) // CLKDIV: PCLK max ~= 25MHz, /25 to give safe 1MHz at fastest 00065 | (0 << 16) // BURST: 0 = software control 00066 | (0 << 17) // CLKS: not applicable 00067 | (1 << 21) // PDN: 1 = operational 00068 | (0 << 24) // START: 0 = no start 00069 | (0 << 27); // EDGE: not applicable 00070 00071 pinmap_pinout(pin, PinMap_ADC); 00072 } 00073 00074 static inline uint32_t adc_read(analogin_t *obj) { 00075 // Select the appropriate channel and start conversion 00076 LPC_ADC->ADCR &= ~0xFF; 00077 LPC_ADC->ADCR |= 1 << (int)obj->adc; 00078 LPC_ADC->ADCR |= 1 << 24; 00079 00080 // Repeatedly get the sample data until DONE bit 00081 unsigned int data; 00082 do { 00083 data = LPC_ADC->ADGDR; 00084 } while ((data & ((unsigned int)1 << 31)) == 0); 00085 00086 // Stop conversion 00087 LPC_ADC->ADCR &= ~(1 << 24); 00088 00089 return (data >> 6) & ADC_RANGE; // 10 bit 00090 } 00091 00092 static inline void order(uint32_t *a, uint32_t *b) { 00093 if (*a > *b) { 00094 uint32_t t = *a; 00095 *a = *b; 00096 *b = t; 00097 } 00098 } 00099 00100 static inline uint32_t adc_read_u32(analogin_t *obj) { 00101 uint32_t value; 00102 #if ANALOGIN_MEDIAN_FILTER 00103 uint32_t v1 = adc_read(obj); 00104 uint32_t v2 = adc_read(obj); 00105 uint32_t v3 = adc_read(obj); 00106 order(&v1, &v2); 00107 order(&v2, &v3); 00108 order(&v1, &v2); 00109 value = v2; 00110 #else 00111 value = adc_read(obj); 00112 #endif 00113 return value; 00114 } 00115 00116 uint16_t analogin_read_u16(analogin_t *obj) { 00117 uint32_t value = adc_read_u32(obj); 00118 00119 return (value << 6) | ((value >> 4) & 0x003F); // 10 bit 00120 } 00121 00122 float analogin_read(analogin_t *obj) { 00123 uint32_t value = adc_read_u32(obj); 00124 return (float)value * (1.0f / (float)ADC_RANGE); 00125 }
Generated on Tue Jul 12 2022 13:47:00 by 1.7.2