From ae3f0193b8485029a4c7303396ee9fc417634b6b Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Tue, 25 Apr 2017 15:29:54 +0200 Subject: [PATCH] cpu/lpc11u34: fixed ADC driver - fixed selection of resolution - fixed result masking - fixed channel selection (and optimized it) - fixed clock prescaler calculation --- cpu/lpc11u34/include/periph_cpu.h | 16 +++++++--------- cpu/lpc11u34/periph/adc.c | 28 ++++++++++++++++++---------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/cpu/lpc11u34/include/periph_cpu.h b/cpu/lpc11u34/include/periph_cpu.h index 0c791c3c68e5..6b283a4af44e 100644 --- a/cpu/lpc11u34/include/periph_cpu.h +++ b/cpu/lpc11u34/include/periph_cpu.h @@ -44,10 +44,8 @@ extern "C" { /** * @brief Define number of available ADC lines - * - * TODO: check this value */ -#define ADC_NUMOF (10U) +#define ADC_NUMOF (8U) /** * @brief Override the default GPIO type @@ -95,12 +93,12 @@ typedef enum { */ #define HAVE_ADC_RES_T typedef enum { - ADC_RES_6BIT = 0, /**< ADC resolution: 6 bit */ - ADC_RES_8BIT, /**< ADC resolution: 8 bit */ - ADC_RES_10BIT, /**< ADC resolution: 10 bit */ - ADC_RES_12BIT, /**< ADC resolution: 12 bit */ - ADC_RES_14BIT, /**< ADC resolution: 14 bit */ - ADC_RES_16BIT, /**< ADC resolution: 16 bit */ + ADC_RES_6BIT = (0x4 << 17), /**< ADC resolution: 6 bit */ + ADC_RES_8BIT = (0x2 << 17), /**< ADC resolution: 8 bit */ + ADC_RES_10BIT = (0x0 << 17), /**< ADC resolution: 10 bit */ + ADC_RES_12BIT = 1, /**< ADC resolution: 12 bit, no supported */ + ADC_RES_14BIT = 2, /**< ADC resolution: 14 bit, no supported */ + ADC_RES_16BIT = 3, /**< ADC resolution: 16 bit, no supported */ } adc_res_t; /** @} */ #endif /* ndef DOXYGEN */ diff --git a/cpu/lpc11u34/periph/adc.c b/cpu/lpc11u34/periph/adc.c index 30ec16bc925c..8f5c5d8c1fd0 100644 --- a/cpu/lpc11u34/periph/adc.c +++ b/cpu/lpc11u34/periph/adc.c @@ -24,8 +24,19 @@ #include "cpu.h" #include "mutex.h" +#include "assert.h" #include "periph/adc.h" +#define START_CMD (0x1 << 24) +#define DONE_BIT (0x1 << 31) +#define RES_MASK (0xf << 17) +#define SAMPLE_SHIFT (6) +#define SAMPLE_MASK (0x3ff) + +/* we chose an ADC clock smaller or equal than but close to 4.5MHz (as proposed + * in the reference manual) */ +#define CLK_DIV (((CLOCK_CORECLOCK / 45000000) & 0xff) << 8) + /** * @brief Mutex to synchronize ADC access from different threads */ @@ -57,8 +68,6 @@ int adc_init(adc_t line) prep(); - /* ADC frequency : 3MHz */ - LPC_ADC->CR = (15 << 8); /* configure the connected pin */ pincfg = pincfg_reg(line); /* Put the pin in its ADC alternate function */ @@ -80,23 +89,22 @@ int adc_sample(adc_t line, adc_res_t res) { int sample; + assert(line < ADC_NUMOF); + /* check if resolution is valid */ - if (res < 0xff) { + if (res & ~(RES_MASK)) { return -1; } /* prepare the device */ prep(); - /* set resolution */ - LPC_ADC->CR &= ~(0x7 << 17); - LPC_ADC->CR |= res; - /* Start a conversion */ - LPC_ADC->CR |= (1 << line) | (1 << 24); + /* start conversion */ + LPC_ADC->CR = ((1 << line) | CLK_DIV | res | START_CMD); /* Wait for the end of the conversion */ - while (!(LPC_ADC->DR[line] & (1 << 31))) {} + while (!(LPC_ADC->DR[line] & DONE_BIT)) {} /* Read and return result */ - sample = (LPC_ADC->DR[line] >> 6); + sample = ((LPC_ADC->DR[line] >> SAMPLE_SHIFT) & SAMPLE_MASK); done();