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_11, ADC0_0, 0x02}, 00032 {P0_12, ADC0_1, 0x02}, 00033 {P0_13, ADC0_2, 0x02}, 00034 {P0_14, ADC0_3, 0x02}, 00035 {P0_15, ADC0_4, 0x02}, 00036 {P0_16, ADC0_5, 0x01}, 00037 {P0_22, ADC0_6, 0x01}, 00038 {P0_23, ADC0_7, 0x01}, 00039 {NC , NC , 0 } 00040 }; 00041 00042 #define LPC_IOCON0_BASE (LPC_IOCON_BASE) 00043 #define LPC_IOCON1_BASE (LPC_IOCON_BASE + 0x60) 00044 00045 #define ADC_RANGE ADC_10BIT_RANGE 00046 00047 void analogin_init(analogin_t *obj, PinName pin) { 00048 obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC); 00049 if (obj->adc == (uint32_t)NC) { 00050 error("ADC pin mapping failed"); 00051 } 00052 00053 // Power up ADC 00054 LPC_SYSCON->PDRUNCFG &= ~ (1 << 4); 00055 LPC_SYSCON->SYSAHBCLKCTRL |= ((uint32_t)1 << 13); 00056 00057 uint32_t pin_number = (uint32_t)pin; 00058 __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)); 00059 00060 // set pin to ADC mode 00061 *reg &= ~(1 << 7); // set ADMODE = 0 (analog mode) 00062 00063 uint32_t PCLK = SystemCoreClock; 00064 uint32_t MAX_ADC_CLK = 4500000; 00065 uint32_t clkdiv = div_round_up(PCLK, MAX_ADC_CLK) - 1; 00066 00067 LPC_ADC->CR = (0 << 0) // no channels selected 00068 | (clkdiv << 8) // max of 4.5MHz 00069 | (0 << 16) // BURST = 0, software controlled 00070 | ( 0 << 17 ); // CLKS = 0, not applicable 00071 00072 pinmap_pinout(pin, PinMap_ADC); 00073 } 00074 00075 static inline uint32_t adc_read(analogin_t *obj) { 00076 // Select the appropriate channel and start conversion 00077 LPC_ADC->CR &= ~0xFF; 00078 LPC_ADC->CR |= 1 << (int)obj->adc; 00079 LPC_ADC->CR |= 1 << 24; 00080 00081 // Repeatedly get the sample data until DONE bit 00082 unsigned int data; 00083 do { 00084 data = LPC_ADC->GDR; 00085 } while ((data & ((unsigned int)1 << 31)) == 0); 00086 00087 // Stop conversion 00088 LPC_ADC->CR &= ~(1 << 24); 00089 00090 return (data >> 6) & ADC_RANGE; // 10 bit 00091 } 00092 00093 static inline void order(uint32_t *a, uint32_t *b) { 00094 if (*a > *b) { 00095 uint32_t t = *a; 00096 *a = *b; 00097 *b = t; 00098 } 00099 } 00100 00101 static inline uint32_t adc_read_u32(analogin_t *obj) { 00102 uint32_t value; 00103 #if ANALOGIN_MEDIAN_FILTER 00104 uint32_t v1 = adc_read(obj); 00105 uint32_t v2 = adc_read(obj); 00106 uint32_t v3 = adc_read(obj); 00107 order(&v1, &v2); 00108 order(&v2, &v3); 00109 order(&v1, &v2); 00110 value = v2; 00111 #else 00112 value = adc_read(obj); 00113 #endif 00114 return value; 00115 } 00116 00117 uint16_t analogin_read_u16(analogin_t *obj) { 00118 uint32_t value = adc_read_u32(obj); 00119 00120 return (value << 6) | ((value >> 4) & 0x003F); // 10 bit 00121 } 00122 00123 float analogin_read(analogin_t *obj) { 00124 uint32_t value = adc_read_u32(obj); 00125 return (float)value * (1.0f / (float)ADC_RANGE); 00126 }
Generated on Tue Jul 12 2022 13:47:00 by 1.7.2