cpu/lpc2387: implement periph/adc

lpc23xx has a 10 bit ADC with up to 8 channels.

The ADC should be clocked at 4.5 MHz or less, so it uses
(72MHz CCLK / 8) / 2.
This commit is contained in:
Benjamin Valentin 2019-12-09 19:43:33 +01:00 committed by Benjamin Valentin
parent 1ad14f3c79
commit 13e578bc84
2 changed files with 110 additions and 0 deletions

View File

@ -153,6 +153,35 @@ typedef enum {
*/ */
#define DAC_NUMOF (1U) #define DAC_NUMOF (1U)
/**
* @brief Possible ADC resolution settings
* @{
*/
#define HAVE_ADC_RES_T
typedef enum {
ADC_RES_16BIT = 0xff, /**< not applicable */
ADC_RES_14BIT = 0xfe, /**< not applicable */
ADC_RES_12BIT = 0xfd, /**< not applicable */
ADC_RES_10BIT = 0b000, /**< ADC resolution: 10 bit */
ADC_RES_9BIT = 0b001, /**< ADC resolution: 9 bit */
ADC_RES_8BIT = 0b010, /**< ADC resolution: 8 bit */
ADC_RES_7BIT = 0b011, /**< ADC resolution: 7 bit */
ADC_RES_6BIT = 0b100, /**< ADC resolution: 6 bit */
ADC_RES_5BIT = 0b101, /**< ADC resolution: 5 bit */
ADC_RES_4BIT = 0b110, /**< ADC resolution: 4 bit */
ADC_RES_3BIT = 0b111, /**< ADC resolution: 3 bit */
} adc_res_t;
/** @} */
/**
* @brief ADC device configuration
*/
typedef struct {
uint8_t chan; /**< which ADC to use (0…7) */
uint8_t pinsel; /**< PINSEL# of the ADC pin */
uint32_t pinsel_msk; /**< PINSEL Mask for ADC pin */
} adc_conf_t;
/* @} */ /* @} */
#ifdef __cplusplus #ifdef __cplusplus
} }

81
cpu/lpc2387/periph/adc.c Normal file
View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2019 Beuth Hochschule für Technik Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup drivers_periph
* @{
*
* @file
* @brief Low-level ADC driver implementation for lpc23xx family
*
* @author Benjamin Valentin <benpicco@beuth-hochschule.de>
*
* @}
*/
#include "cpu.h"
#include "kernel_defines.h"
#include "periph/adc.h"
#include "periph_conf.h"
int adc_init(adc_t line)
{
/* check if the line is valid */
if (line >= ADC_NUMOF) {
return -1;
}
/* enable clock/power for ADC */
PCONP |= BIT12;
/* set ADC PCLK to CCLK/8 */
PCLKSEL0 |= BIT25 + BIT25;
/* configure AF for ADC pin */
*(&PINSEL0 + adc_config[line].pinsel) |= adc_config[line].pinsel_msk;
/* power down ADC */
AD0CR = 0;
return 0;
}
int32_t adc_sample(adc_t line, adc_res_t res)
{
uint32_t val;
/* check if the line is valid */
if (line >= ADC_NUMOF) {
return -1;
}
/* check if resolution is applicable */
if (res > 0xf0) {
return -1;
}
/* Enable & configure ADC.
* burst mode is used even though we only do one conversion here
* in order to being able to configure the resolution.
*/
AD0CR = (1 << adc_config[line].chan) /* select channel */
| (1 << 8) /* clocked at 4.5 MHz */
| (1 << 16) /* enable burst mode */
| (res << 17) /* select resolution */
| (1 << 21) /* enable ADC */
| (1 << 24); /* start conversion */
do {
val = *(&AD0DR0 + adc_config[line].chan);
} while (!(val & BIT31));
/* power down ADC */
AD0CR = 0;
return val & 0xFFFF;
}