diff --git a/boards/frdm-k22f/include/periph_conf.h b/boards/frdm-k22f/include/periph_conf.h index 6dd838a39f..3d769c85f9 100644 --- a/boards/frdm-k22f/include/periph_conf.h +++ b/boards/frdm-k22f/include/periph_conf.h @@ -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])) diff --git a/boards/frdm-k64f/include/periph_conf.h b/boards/frdm-k64f/include/periph_conf.h index 0985498588..f27cd18198 100644 --- a/boards/frdm-k64f/include/periph_conf.h +++ b/boards/frdm-k64f/include/periph_conf.h @@ -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])) diff --git a/boards/frdm-kw41z/include/periph_conf.h b/boards/frdm-kw41z/include/periph_conf.h index b0278e909a..2330c1a386 100644 --- a/boards/frdm-kw41z/include/periph_conf.h +++ b/boards/frdm-kw41z/include/periph_conf.h @@ -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])) /* diff --git a/boards/mulle/include/periph_conf.h b/boards/mulle/include/periph_conf.h index b3b11ffd80..491cf2ca89 100644 --- a/boards/mulle/include/periph_conf.h +++ b/boards/mulle/include/periph_conf.h @@ -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])) diff --git a/boards/pba-d-01-kw2x/include/periph_conf.h b/boards/pba-d-01-kw2x/include/periph_conf.h index 0460b29734..c8afe2c38c 100644 --- a/boards/pba-d-01-kw2x/include/periph_conf.h +++ b/boards/pba-d-01-kw2x/include/periph_conf.h @@ -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])) diff --git a/cpu/kinetis/include/periph_cpu.h b/cpu/kinetis/include/periph_cpu.h index 4f88ea5649..8acb05a60b 100644 --- a/cpu/kinetis/include/periph_cpu.h +++ b/cpu/kinetis/include/periph_cpu.h @@ -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 diff --git a/cpu/kinetis/periph/adc.c b/cpu/kinetis/periph/adc.c index 9a8da6a1d2..2648637578 100644 --- a/cpu/kinetis/periph/adc.c +++ b/cpu/kinetis/periph/adc.c @@ -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 */