1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-26 15:03:53 +01:00

Merge pull request #9807 from gebart/pr/kinetis-adc-average

kinetis: ADC: Add hardware averaging configuration
This commit is contained in:
Joakim Nohlgård 2018-09-26 12:54:29 +02:00 committed by GitHub
commit 7a857a939c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 108 additions and 67 deletions

View File

@ -127,14 +127,22 @@ static const uart_conf_t uart_config[] = {
*/
static const adc_conf_t adc_config[] = {
/* dev, pin, channel */
{ .dev = ADC0, .pin = GPIO_UNDEF , .chan = 0 }, /* ADC0_DP0 */
{ .dev = ADC0, .pin = GPIO_UNDEF , .chan = 19 }, /* ADC0_DM0 */
{ .dev = ADC1, .pin = GPIO_UNDEF , .chan = 0 }, /* ADC1_DP0 */
{ .dev = ADC1, .pin = GPIO_UNDEF , .chan = 19 }, /* ADC1_DM0 */
{ .dev = ADC0, .pin = GPIO_PIN(PORT_B, 0), .chan = 8 }, /* PTB0 (Arduino A0) */
{ .dev = ADC0, .pin = GPIO_PIN(PORT_B, 1), .chan = 9 }, /* PTB1 (Arduino A1) */
{ .dev = ADC0, .pin = GPIO_PIN(PORT_C, 1), .chan = 15 }, /* PTC1 (Arduino A2) */
{ .dev = ADC0, .pin = GPIO_PIN(PORT_C, 2), .chan = 4 }, /* PTC2 (Arduino A3) */
[ 0] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = 0, .avg = ADC_AVG_MAX }, /* ADC0_DP0 */
[ 1] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = 19, .avg = ADC_AVG_MAX }, /* ADC0_DM0 */
[ 2] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = 0, .avg = ADC_AVG_MAX }, /* ADC1_DP0 */
[ 3] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = 19, .avg = ADC_AVG_MAX }, /* ADC1_DM0 */
[ 4] = { .dev = ADC0, .pin = GPIO_PIN(PORT_B, 0), .chan = 8, .avg = ADC_AVG_MAX }, /* PTB0 (Arduino A0) */
[ 5] = { .dev = ADC0, .pin = GPIO_PIN(PORT_B, 1), .chan = 9, .avg = ADC_AVG_MAX }, /* PTB1 (Arduino A1) */
[ 6] = { .dev = ADC0, .pin = GPIO_PIN(PORT_C, 1), .chan = 15, .avg = ADC_AVG_MAX }, /* PTC1 (Arduino A2) */
[ 7] = { .dev = ADC0, .pin = GPIO_PIN(PORT_C, 2), .chan = 4, .avg = ADC_AVG_MAX }, /* PTC2 (Arduino A3) */
/* internal: temperature sensor */
/* The temperature sensor has a very high output impedance, it must not be
* sampled using hardware averaging, or the sampled values will be garbage */
[ 8] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 26, .avg = ADC_AVG_NONE },
/* internal: band gap */
/* Note: the band gap buffer uses a bit of current and is turned off by default,
* Set PMC->REGSC |= PMC_REGSC_BGBE_MASK before reading or the input will be floating */
[ 9] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 27, .avg = ADC_AVG_MAX },
};
#define ADC_NUMOF (sizeof(adc_config) / sizeof(adc_config[0]))

View File

@ -120,32 +120,32 @@ static const uart_conf_t uart_config[] = {
* @{
*/
static const adc_conf_t adc_config[] = {
[ 0] = { .dev = ADC0, .pin = GPIO_PIN(PORT_B, 2), .chan = 12 }, /* PTB2 (Arduino A0) */
[ 1] = { .dev = ADC0, .pin = GPIO_PIN(PORT_B, 3), .chan = 13 }, /* PTB3 (Arduino A1) */
[ 2] = { .dev = ADC1, .pin = GPIO_PIN(PORT_B, 10), .chan = 14 }, /* PTB10 (Arduino A2) */
[ 3] = { .dev = ADC1, .pin = GPIO_PIN(PORT_B, 11), .chan = 15 }, /* PTB11 (Arduino A3) */
[ 4] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 11), .chan = 7 }, /* PTC11 (Arduino A4) */
[ 5] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 10), .chan = 6 }, /* PTC10 (Arduino A5) */
[ 6] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = 0 }, /* ADC0_DP0 */
[ 7] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = 19 }, /* ADC0_DM0 */
[ 8] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = (0 | ADC_SC1_DIFF_MASK) }, /* ADC0_DP0 - ADC0_DM0 */
[ 9] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = 0 }, /* ADC1_DP0 */
[10] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = 19 }, /* ADC1_DM0 */
[11] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = (0 | ADC_SC1_DIFF_MASK) }, /* ADC1_DP0 - ADC1_DM0 */
[12] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = 1 }, /* ADC0_DP1 */
[13] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = 20 }, /* ADC0_DM1 */
[14] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = (1 | ADC_SC1_DIFF_MASK) }, /* ADC0_DP1 - ADC0_DM1 */
[15] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = 1 }, /* ADC1_DP1 */
[16] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = 20 }, /* ADC1_DM1 */
[17] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = (1 | ADC_SC1_DIFF_MASK) }, /* ADC1_DP1 - ADC1_DM1 */
[ 0] = { .dev = ADC0, .pin = GPIO_PIN(PORT_B, 2), .chan = 12, .avg = ADC_AVG_MAX }, /* PTB2 (Arduino A0) */
[ 1] = { .dev = ADC0, .pin = GPIO_PIN(PORT_B, 3), .chan = 13, .avg = ADC_AVG_MAX }, /* PTB3 (Arduino A1) */
[ 2] = { .dev = ADC1, .pin = GPIO_PIN(PORT_B, 10), .chan = 14, .avg = ADC_AVG_MAX }, /* PTB10 (Arduino A2) */
[ 3] = { .dev = ADC1, .pin = GPIO_PIN(PORT_B, 11), .chan = 15, .avg = ADC_AVG_MAX }, /* PTB11 (Arduino A3) */
[ 4] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 11), .chan = 7, .avg = ADC_AVG_MAX }, /* PTC11 (Arduino A4) */
[ 5] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 10), .chan = 6, .avg = ADC_AVG_MAX }, /* PTC10 (Arduino A5) */
[ 6] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = 0, .avg = ADC_AVG_MAX }, /* ADC0_DP0 */
[ 7] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = 19, .avg = ADC_AVG_MAX }, /* ADC0_DM0 */
[ 8] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = (0 | ADC_SC1_DIFF_MASK), .avg = ADC_AVG_MAX }, /* ADC0_DP0 - ADC0_DM0 */
[ 9] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = 0, .avg = ADC_AVG_MAX }, /* ADC1_DP0 */
[10] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = 19, .avg = ADC_AVG_MAX }, /* ADC1_DM0 */
[11] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = (0 | ADC_SC1_DIFF_MASK), .avg = ADC_AVG_MAX }, /* ADC1_DP0 - ADC1_DM0 */
[12] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = 1, .avg = ADC_AVG_MAX }, /* ADC0_DP1 */
[13] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = 20, .avg = ADC_AVG_MAX }, /* ADC0_DM1 */
[14] = { .dev = ADC0, .pin = GPIO_UNDEF , .chan = (1 | ADC_SC1_DIFF_MASK), .avg = ADC_AVG_MAX }, /* ADC0_DP1 - ADC0_DM1 */
[15] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = 1, .avg = ADC_AVG_MAX }, /* ADC1_DP1 */
[16] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = 20, .avg = ADC_AVG_MAX }, /* ADC1_DM1 */
[17] = { .dev = ADC1, .pin = GPIO_UNDEF , .chan = (1 | ADC_SC1_DIFF_MASK), .avg = ADC_AVG_MAX }, /* ADC1_DP1 - ADC1_DM1 */
/* internal: temperature sensor */
/* The temperature sensor has a very high output impedance, it must not be
* sampled using hardware averaging, or the sampled values will be garbage */
[18] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 26 },
[18] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 26, .avg = ADC_AVG_NONE },
/* internal: band gap */
/* Note: the band gap buffer uses a bit of current and is turned off by default,
* Set PMC->REGSC |= PMC_REGSC_BGBE_MASK before reading or the input will be floating */
[19] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 27 },
[19] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 27, .avg = ADC_AVG_MAX },
};
#define ADC_NUMOF (sizeof(adc_config) / sizeof(adc_config[0]))

View File

@ -129,21 +129,23 @@ static const uart_conf_t uart_config[] = {
static const adc_conf_t adc_config[] = {
/* dev, pin, channel */
/* ADC0_DP-ADC0_DM differential reading (Arduino A5 - A0) */
[ 0] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 0 | ADC_SC1_DIFF_MASK },
[ 0] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 0 | ADC_SC1_DIFF_MASK, .avg = ADC_AVG_MAX },
/* ADC0_DP single ended reading (Arduino A5) */
[ 1] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 0 },
[ 1] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 0, .avg = ADC_AVG_MAX },
/* PTB2 (Arduino A2) */
[ 2] = { .dev = ADC0, .pin = GPIO_PIN(PORT_B, 2), .chan = 3 },
[ 2] = { .dev = ADC0, .pin = GPIO_PIN(PORT_B, 2), .chan = 3, .avg = ADC_AVG_MAX },
/* PTB3 (Arduino A3) */
[ 3] = { .dev = ADC0, .pin = GPIO_PIN(PORT_B, 3), .chan = 2 },
[ 3] = { .dev = ADC0, .pin = GPIO_PIN(PORT_B, 3), .chan = 2, .avg = ADC_AVG_MAX },
/* internal: temperature sensor */
[ 4] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 26 },
/* The temperature sensor has a very high output impedance, it must not be
* sampled using hardware averaging, or the sampled values will be garbage */
[ 4] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 26, .avg = ADC_AVG_NONE },
/* Note: the band gap buffer uses a bit of current and is turned off by default,
* Set PMC->REGSC |= PMC_REGSC_BGBE_MASK before reading or the input will be floating */
/* internal: band gap */
[ 5] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 27 },
[ 5] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 27, .avg = ADC_AVG_MAX },
/* internal: DCDC divided battery level */
[ 6] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 23 },
[ 6] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 23, .avg = ADC_AVG_MAX },
};
#define ADC_NUMOF (sizeof(adc_config) / sizeof(adc_config[0]))
/*

View File

@ -165,39 +165,41 @@ static const uart_conf_t uart_config[] = {
*/
static const adc_conf_t adc_config[] = {
/* internal: temperature sensor */
[ 0] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 26 },
/* The temperature sensor has a very high output impedance, it must not be
* sampled using hardware averaging, or the sampled values will be garbage */
[ 0] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 26, .avg = ADC_AVG_NONE },
/* internal: band gap */
[ 1] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 27 },
[ 1] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 27, .avg = ADC_AVG_MAX },
/* internal: V_REFSH */
[ 2] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 29 },
[ 2] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 29, .avg = ADC_AVG_MAX },
/* internal: V_REFSL */
[ 3] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 30 },
[ 3] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 30, .avg = ADC_AVG_MAX },
/* internal: DAC0 module output level */
[ 4] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 23 },
[ 4] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 23, .avg = ADC_AVG_MAX },
/* internal: VREF module output level */
[ 5] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 18 },
/* on board connection to Mulle Vbat/2 on PGA1_DP pin */
[ 6] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 0 },
[ 5] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 18, .avg = ADC_AVG_MAX },
/* on board connection to Mulle Vbat/2 on PGA1_DP pin */
[ 6] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 0, .avg = ADC_AVG_MAX },
/* on board connection to Mulle Vchr/2 on PGA1_DM pin */
[ 7] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 19 },
[ 7] = { .dev = ADC1, .pin = GPIO_UNDEF, .chan = 19, .avg = ADC_AVG_MAX },
/* expansion port PGA0_DP pin */
[ 8] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 0 },
[ 8] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 0, .avg = ADC_AVG_MAX },
/* expansion port PGA0_DM pin */
[ 9] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 19 },
[ 9] = { .dev = ADC0, .pin = GPIO_UNDEF, .chan = 19, .avg = ADC_AVG_MAX },
/* expansion port PTA17 */
[10] = { .dev = ADC1, .pin = GPIO_PIN(PORT_A, 17), .chan = 17 },
[10] = { .dev = ADC1, .pin = GPIO_PIN(PORT_A, 17), .chan = 17, .avg = ADC_AVG_MAX },
/* expansion port PTB0 */
[11] = { .dev = ADC1, .pin = GPIO_PIN(PORT_B, 0), .chan = 8 },
[11] = { .dev = ADC1, .pin = GPIO_PIN(PORT_B, 0), .chan = 8, .avg = ADC_AVG_MAX },
/* expansion port PTC0 */
[12] = { .dev = ADC0, .pin = GPIO_PIN(PORT_C, 0), .chan = 14 },
[12] = { .dev = ADC0, .pin = GPIO_PIN(PORT_C, 0), .chan = 14, .avg = ADC_AVG_MAX },
/* expansion port PTC8 */
[13] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 8), .chan = 4 },
[13] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 8), .chan = 4, .avg = ADC_AVG_MAX },
/* expansion port PTC9 */
[14] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 9), .chan = 5 },
[14] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 9), .chan = 5, .avg = ADC_AVG_MAX },
/* expansion port PTC10 */
[15] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 10), .chan = 6 },
[15] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 10), .chan = 6, .avg = ADC_AVG_MAX },
/* expansion port PTC11 */
[16] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 11), .chan = 7 }
[16] = { .dev = ADC1, .pin = GPIO_PIN(PORT_C, 11), .chan = 7, .avg = ADC_AVG_MAX },
};
#define ADC_NUMOF (sizeof(adc_config) / sizeof(adc_config[0]))

View File

@ -135,12 +135,12 @@ static const uart_conf_t uart_config[] = {
* @{
*/
static const adc_conf_t adc_config[] = {
{ .dev = ADC0, .pin = GPIO_PIN(PORT_E, 2), .chan = 1 },
{ .dev = ADC0, .pin = GPIO_PIN(PORT_E, 3), .chan = 1 },
{ .dev = ADC0, .pin = GPIO_PIN(PORT_D, 7), .chan = 22 },
{ .dev = ADC0, .pin = GPIO_PIN(PORT_D, 5), .chan = 6 },
{ .dev = ADC0, .pin = GPIO_PIN(PORT_E, 0), .chan = 10 },
{ .dev = ADC0, .pin = GPIO_PIN(PORT_E, 1), .chan = 11 }
[ 0] = { .dev = ADC0, .pin = GPIO_PIN(PORT_E, 2), .chan = 1, .avg = ADC_AVG_MAX },
[ 1] = { .dev = ADC0, .pin = GPIO_PIN(PORT_E, 3), .chan = 1, .avg = ADC_AVG_MAX },
[ 2] = { .dev = ADC0, .pin = GPIO_PIN(PORT_D, 7), .chan = 22, .avg = ADC_AVG_MAX },
[ 3] = { .dev = ADC0, .pin = GPIO_PIN(PORT_D, 5), .chan = 6, .avg = ADC_AVG_MAX },
[ 4] = { .dev = ADC0, .pin = GPIO_PIN(PORT_E, 0), .chan = 10, .avg = ADC_AVG_MAX },
[ 5] = { .dev = ADC0, .pin = GPIO_PIN(PORT_E, 1), .chan = 11, .avg = ADC_AVG_MAX }
};
#define ADC_NUMOF (sizeof(adc_config) / sizeof(adc_config[0]))

View File

@ -274,12 +274,40 @@ typedef enum {
* @brief CPU specific ADC configuration
*/
typedef struct {
ADC_Type *dev; /**< ADC device */
gpio_t pin; /**< pin to use, set to GPIO_UNDEF for internal
* channels */
uint8_t chan; /**< ADC channel */
/**
* @brief ADC module
*/
ADC_Type *dev;
/**
* @brief pin to use
*
* Use GPIO_UNDEF non-muxed ADC pins, e.g. ADC0_DP, or for internal channels, e.g. Bandgap
*/
gpio_t pin;
/**
* @brief ADC channel
*
* Written as-is to ADCx_SC1x before conversion. This also decides
* single-ended or differential sampling, see CPU reference manual for ADCx_SC1x
*/
uint8_t chan;
/**
* @brief Hardware averaging configuration
*
* Written as-is to ADCx_SC3 before conversion, use @ref ADC_AVG_NONE and
* @ref ADC_AVG_MAX as a shorthand notation in the board configuration */
uint8_t avg;
} adc_conf_t;
/**
* @brief Disable hardware averaging
*/
#define ADC_AVG_NONE (0)
/**
* @brief Maximum hardware averaging (32 samples)
*/
#define ADC_AVG_MAX (ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(3))
#if defined(DAC0_BASE) && (DAC0_BASE != This_symbol_has_been_deprecated)
/**
* @brief CPU specific DAC configuration

View File

@ -197,10 +197,9 @@ int adc_init(adc_t line)
dev(line)->CFG2 = ADC_CFG2_MUXSEL_MASK | ADC_CFG2_ADLSTS(0);
/* select software trigger, external ref pins */
dev(line)->SC2 = ADC_SC2_REFSEL(ADC_REF_SETTING);
/* select hardware average over 32 samples */
dev(line)->SC3 = ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(3);
/* set an (arbitrary) input channel, single-ended mode */
dev(line)->SC1[0] = ADC_SC1_ADCH(0);
/* set an arbitrary input channel configuration */
dev(line)->SC3 = 0;
dev(line)->SC1[0] = ADC_SC1_ADCH(31);
/* perform calibration routine */
int res = kinetis_adc_calibrate(dev(line));
@ -223,6 +222,8 @@ int adc_sample(adc_t line, adc_res_t res)
/* set resolution */
dev(line)->CFG1 &= ~(ADC_CFG1_MODE_MASK);
dev(line)->CFG1 |= (res);
/* set the chosen hardware averaging setting for this channel */
dev(line)->SC3 = adc_config[line].avg;
/* select the channel that is sampled */
dev(line)->SC1[0] = adc_config[line].chan;
/* wait until conversion is complete */