application: add ADC to measure target and signal voltage
This commit is contained in:
parent
474472fcf4
commit
2b718bfc72
|
@ -24,6 +24,7 @@
|
||||||
#include <libopencm3/stm32/dbgmcu.h> // debug utilities
|
#include <libopencm3/stm32/dbgmcu.h> // debug utilities
|
||||||
#include <libopencm3/stm32/desig.h> // design utilities
|
#include <libopencm3/stm32/desig.h> // design utilities
|
||||||
#include <libopencm3/stm32/flash.h> // flash utilities
|
#include <libopencm3/stm32/flash.h> // flash utilities
|
||||||
|
#include <libopencm3/stm32/adc.h> // ADC utilities
|
||||||
|
|
||||||
/* own libraries */
|
/* own libraries */
|
||||||
#include "global.h" // board definitions
|
#include "global.h" // board definitions
|
||||||
|
@ -68,6 +69,29 @@ size_t putc(char c)
|
||||||
return length; // return number of characters printed
|
return length; // return number of characters printed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TARGET_CHANNEL 1 /**< PA1/ADC1_IN1 used to measure target voltage */
|
||||||
|
#define SIGNAL_CHANNEL 2 /**< PA2/ADC1_IN2 used to measure signal voltage */
|
||||||
|
const uint8_t channels[] = {ADC_CHANNEL17, ADC_CHANNEL(TARGET_CHANNEL), ADC_CHANNEL(SIGNAL_CHANNEL)}; /**< voltages to convert (channel 17 = internal voltage reference) */
|
||||||
|
|
||||||
|
/** measure target and signal voltages
|
||||||
|
* @return voltages of channels
|
||||||
|
*/
|
||||||
|
static float* measure_voltages(void)
|
||||||
|
{
|
||||||
|
static float voltages[LENGTH(channels)]; // to store and return the voltages
|
||||||
|
|
||||||
|
// read lid temperature using ADC
|
||||||
|
ADC_SR(ADC1) = 0; // reset flags
|
||||||
|
uint16_t adc_values[LENGTH(channels)];
|
||||||
|
for (uint8_t i = 0; i < LENGTH(channels); i++) {
|
||||||
|
adc_start_conversion_regular(ADC1); // start conversion (using trigger)
|
||||||
|
while (!adc_eoc(ADC1)); // wait until conversion finished
|
||||||
|
adc_values[i] = adc_read_regular(ADC1); // read voltage value (clears flag)
|
||||||
|
voltages[i] = adc_values[i] * 1.21 / adc_values[0] * 2; // use 1.21 V internal voltage reference to get ADC voltage (there is a /2 voltage divider)
|
||||||
|
}
|
||||||
|
return voltages;
|
||||||
|
}
|
||||||
|
|
||||||
// menu commands
|
// menu commands
|
||||||
|
|
||||||
static void command_swd_scan(void* argument)
|
static void command_swd_scan(void* argument)
|
||||||
|
@ -493,10 +517,34 @@ void main(void)
|
||||||
// important: do not re-enable backup_domain_write_protect, since this will prevent clearing flags (but RTC registers do not need to be unlocked)
|
// important: do not re-enable backup_domain_write_protect, since this will prevent clearing flags (but RTC registers do not need to be unlocked)
|
||||||
puts("OK\n");
|
puts("OK\n");
|
||||||
|
|
||||||
puts("setup SWD: ");
|
puts("setup ADC to measure voltages: ");
|
||||||
swd_setup(100000); // setup SWD clock to 100 KHz, slow enough for any target and loose connection
|
rcc_periph_clock_enable(RCC_ADC1); // enable clock for ADC domain
|
||||||
|
adc_power_off(ADC1); // switch off ADC while configuring it
|
||||||
|
adc_set_right_aligned(ADC1); // ensure it is right aligned to get the actual value in the 16-bit register
|
||||||
|
adc_enable_scan_mode(ADC1); // use scan mode do be able to go to next discontinuous subgroup of the regular sequence
|
||||||
|
adc_enable_discontinuous_mode_regular(ADC1, 1); // use discontinuous mode (to go through all channels of the group, one after another)
|
||||||
|
adc_set_single_conversion_mode(ADC1); // ensure continuous mode is not used (that's not the same as discontinuous)
|
||||||
|
adc_eoc_after_each(ADC1); // set EOC after each conversion instead of each group
|
||||||
|
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28CYC); // use at least 15 cycles to be able to sample at 12-bit resolution
|
||||||
|
adc_set_regular_sequence(ADC1, LENGTH(channels), (uint8_t*)channels); // set channel to convert
|
||||||
|
adc_enable_temperature_sensor(); // enable internal voltage reference
|
||||||
|
adc_power_on(ADC1); // switch on ADC
|
||||||
|
sleep_us(3); // wait t_stab for the ADC to stabilize
|
||||||
|
rcc_periph_clock_enable(RCC_ADC1_IN(TARGET_CHANNEL)); // enable clock for GPIO domain for target voltage channel
|
||||||
|
gpio_mode_setup(ADC1_IN_PORT(TARGET_CHANNEL), GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC1_IN_PIN(TARGET_CHANNEL)); // set target voltage channel as analog input for the ADC
|
||||||
|
rcc_periph_clock_enable(RCC_ADC1_IN(SIGNAL_CHANNEL)); // enable clock for GPIO domain for signal channel
|
||||||
|
gpio_mode_setup(ADC1_IN_PORT(SIGNAL_CHANNEL), GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC1_IN_PIN(SIGNAL_CHANNEL)); // set signal channel as analog input for the ADC
|
||||||
|
measure_voltages(); // try to measure voltages
|
||||||
puts("OK\n");
|
puts("OK\n");
|
||||||
|
|
||||||
|
puts("setup SWD: ");
|
||||||
|
if (!swd_set_pins(GPIO_PORT(PB10), GPIO_PIN(PB10), GPIO_PORT(PB2), GPIO_PIN(PB2))) {
|
||||||
|
puts("unknown pins\n");
|
||||||
|
} else {
|
||||||
|
swd_setup(100000); // setup SWD clock to 100 KHz, slow enough for any target and loose connection
|
||||||
|
puts("OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
// setup terminal
|
// setup terminal
|
||||||
terminal_prefix = ""; // set default prefix
|
terminal_prefix = ""; // set default prefix
|
||||||
terminal_process = &process_command; // set central function to process commands
|
terminal_process = &process_command; // set central function to process commands
|
||||||
|
|
Loading…
Reference in New Issue