BV: fix ADC blocking (caused by delays added by USB interrupts)

This commit is contained in:
King Kévin 2018-04-28 13:56:03 +02:00
parent c0c9b83543
commit 5ea67d2250
1 changed files with 30 additions and 24 deletions

View File

@ -101,10 +101,10 @@ void busvoodoo_setup(void)
rcc_periph_clock_enable(RCC_ADC1); // enable clock for ADC domain
adc_power_off(ADC1); // switch off ADC while configuring it
adc_disable_scan_mode(ADC1); // ensure scan mode is disabled
adc_disable_discontinuous_mode_regular(ADC1); // ensure discontinuous mode is not used
adc_set_single_conversion_mode(ADC1); // ensure continuous mode is not used (that's not the same as discontinuous)
adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); // use 28.5 cycles to sample (long enough to be stable)
adc_enable_temperature_sensor(); // enable internal voltage reference
adc_enable_external_trigger_regular(ADC1, ADC_CR2_EXTSEL_SWSTART); // use software trigger to start conversion
adc_set_single_conversion_mode(ADC1); // we only convert one channel after another
adc_power_on(ADC1); // switch on ADC
sleep_us(1); // wait t_stab for the ADC to stabilize
adc_reset_calibration(ADC1); // remove previous non-calibration
@ -232,58 +232,64 @@ float busvoodoo_vreg_get(uint8_t channel)
return NAN;
}
uint8_t channels[2] = {ADC_CHANNEL17, ADC_CHANNEL17}; // voltages to convert: internal and internal (as fallback)
switch (channel) { // set desired channel
// start by reading the internal voltage
uint8_t channels[1] = {ADC_CHANNEL17}; // voltages to convert: internal
adc_set_regular_sequence(ADC1, LENGTH(channels), channels); // set channel to convert
ADC_SR(ADC1) = 0; // reset flags
adc_start_conversion_direct(ADC1); // start conversion (without using trigger)
while (!adc_eoc(ADC1)); // wait until conversion finished
uint16_t internal_value = adc_read_regular(ADC1); // read voltage value (clears flag)
// read desired voltage
switch (channel) {
case BUSVOODOO_5V_CHANNEL:
channels[1] = ADC_CHANNEL(BUSVOODOO_5V_CHANNEL);
channels[0] = ADC_CHANNEL(BUSVOODOO_5V_CHANNEL);
break;
case BUSVOODOO_3V3_CHANNEL:
channels[1] = ADC_CHANNEL(BUSVOODOO_3V3_CHANNEL);
channels[0] = ADC_CHANNEL(BUSVOODOO_3V3_CHANNEL);
break;
case BUSVOODOO_LV_CHANNEL:
channels[1] = ADC_CHANNEL(BUSVOODOO_LV_CHANNEL);
channels[0] = ADC_CHANNEL(BUSVOODOO_LV_CHANNEL);
break;
case BUSVOODOO_HV_CHANNEL:
channels[1] = ADC_CHANNEL(BUSVOODOO_HV_CHANNEL);
channels[0] = ADC_CHANNEL(BUSVOODOO_HV_CHANNEL);
break;
case BUSVOODOO_HW_VERSION_CHANNEL:
channels[1] = ADC_CHANNEL(BUSVOODOO_HW_VERSION_CHANNEL);
channels[0] = ADC_CHANNEL(BUSVOODOO_HW_VERSION_CHANNEL);
break;
default: // unknown channel
break;
return NAN;
}
adc_set_regular_sequence(ADC1, LENGTH(channels), channels); // set channels to convert
adc_enable_discontinuous_mode_regular(ADC1, LENGTH(channels)); // convert all channels
uint16_t values[LENGTH(channels)] = {0}; // to store converted values
adc_set_regular_sequence(ADC1, LENGTH(channels), channels); // set channel to convert
ADC_SR(ADC1) = 0; // reset flags
adc_start_conversion_regular(ADC1); // start conversion for individual channels
for (uint8_t channel_i=0; channel_i<LENGTH(channels); channel_i++) { // get all conversions
while (!adc_eoc(ADC1)); // wait until conversion finished
values[channel_i] = adc_read_regular(ADC1); // read voltage value (clears flag)
}
adc_start_conversion_direct(ADC1); // start conversion (without using trigger)
while (!adc_eoc(ADC1)); // wait until conversion finished
uint16_t desired_value = adc_read_regular(ADC1); // read voltage value (clears flag)
// calculate desired voltage
float to_return = NAN; // voltage to return
switch (channel) { // get converted value and calculate according to the voltage divider on this channel
case BUSVOODOO_5V_CHANNEL:
to_return = values[1]/(10.0/(10.0+10.0));
to_return = desired_value/(10.0/(10.0+10.0));
break;
case BUSVOODOO_3V3_CHANNEL:
to_return = values[1]/(10.0/(10.0+10.0));
to_return = desired_value/(10.0/(10.0+10.0));
break;
case BUSVOODOO_LV_CHANNEL:
to_return = values[1]/(10.0/(10.0+10.0));
to_return = desired_value/(10.0/(10.0+10.0));
break;
case BUSVOODOO_HV_CHANNEL:
to_return = values[1]/(1.5/(10.0+1.5));
to_return = desired_value/(1.5/(10.0+1.5));
break;
case BUSVOODOO_HW_VERSION_CHANNEL:
to_return = values[1];
to_return = desired_value;
break;
default: // unknown channel
to_return = NAN;
break;
}
if (!isnan(to_return)) {
to_return *= 1.2/values[0]; // calculate voltage from converted values using internal 1.2V voltage reference
to_return *= 1.2/internal_value; // calculate voltage from converted values using internal 1.2V voltage reference
}
return to_return;
}