diff --git a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp index 33774a55..65f3e8cb 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp @@ -1,12 +1,8 @@ #include "stm32_adc_utils.h" +#include "stm32_mcu.h" #if defined(_STM32_DEF_) -// for searching the best ADCs, we need to know the number of ADCs -// it might be better to use some HAL variable for example ADC_COUNT -// here I've assumed the maximum number of ADCs is 5 -#define ADC_COUNT 5 - int _adcToIndex(ADC_TypeDef *AdcHandle){ @@ -344,4 +340,91 @@ uint32_t _getADCInjectedRank(uint8_t ind){ } } +// returns 0 if no interrupt is needed, 1 if interrupt is needed +uint32_t _initTimerInterruptDownsampling(Stm32CurrentSenseParams* cs_params, STM32DriverParams* driver_params, Stm32AdcInterruptConfig& adc_interrupt_config){ + + // If DIR is 0 (upcounting), the next event is high-side active (PWM rising edge) + // If DIR is 1 (downcounting), the next event is low-side active (PWM falling edge) + bool next_event_high_side = (cs_params->timer_handle->Instance->CR1 & TIM_CR1_DIR) == 0; + + // if timer has repetition counter - it will downsample using it + // and it does not need the software downsample + if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){ + // adjust the initial timer state such that the trigger + // - only necessary for the timers that have repetition counters + // - basically make sure that the next trigger event is the one that is expected (high-side first then low-side) + + // set the direction and the + for(int i=0; i< 6; i++){ + if(driver_params->timers_handle[i] == NP) continue; // skip if not set + if(next_event_high_side){ + // Set DIR bit to 0 (downcounting) + driver_params->timers_handle[i]->Instance->CR1 |= TIM_CR1_DIR; + // Set CNT to ARR so it starts upcounting from the top + driver_params->timers_handle[i]->Instance->CNT = driver_params->timers_handle[i]->Instance->ARR; + }else{ + // Set DIR bit to 0 (upcounting) + driver_params->timers_handle[i]->Instance->CR1 &= ~TIM_CR1_DIR; + // Set CNT to ARR so it starts upcounting from zero + driver_params->timers_handle[i]->Instance->CNT = 0;// driver_params->timers_handle[i]->Instance->ARR; + } + } + return 0; // no interrupt is needed, the timer will handle the downsampling + }else{ + if(!adc_interrupt_config.use_adc_interrupt){ + // If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing + adc_interrupt_config.use_adc_interrupt = 1; + // remember that this timer does not have the repetition counter - need to downasmple + adc_interrupt_config.needs_downsample = 1; + + if(next_event_high_side) // Next event is high-side active + adc_interrupt_config.tim_downsample = 0; // skip the next interrupt (and every second one) + else // Next event is low-side active + adc_interrupt_config.tim_downsample = 1; // read the next one (and every second one after) + + return 1; // interrupt is needed + } + } + return 1; // interrupt is needed +} + +// returns 0 if no downsampling is needed, 1 if downsampling is needed, 2 if error +uint8_t _handleInjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle, Stm32AdcInterruptConfig& adc_interrupt_config, uint32_t adc_val[4]) { + + // if the timer han't repetition counter - downsample two times + if( adc_interrupt_config.needs_downsample && adc_interrupt_config.tim_downsample++ > 0) { + adc_interrupt_config.tim_downsample = 0; + return 1; + } + + adc_val[0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1); + adc_val[1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2); + adc_val[2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3); + adc_val[3]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_4); + + return 0; // no downsampling needed +} + +// reads the ADC injected voltage for the given pin +// returns the voltage +// if the pin is not found in the current sense parameters, returns 0 +float _readADCInjectedChannelVoltage(int pin, void* cs_params, Stm32AdcInterruptConfig& adc_interrupt_config, uint32_t adc_val[4]) { + Stm32CurrentSenseParams* cs_p = (Stm32CurrentSenseParams*)cs_params; + uint8_t channel_no = 0; + uint8_t adc_index = (uint8_t)_adcToIndex(cs_p->adc_handle); + for(int i=0; i < 3; i++){ + if( pin == cs_p->pins[i]){ // found in the buffer + if (adc_interrupt_config.use_adc_interrupt){ + return adc_val[channel_no] * cs_p->adc_voltage_conv; + }else{ + // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 + uint32_t channel = _getADCInjectedRank(channel_no); + return HAL_ADCEx_InjectedGetValue(cs_p->adc_handle, channel) * cs_p->adc_voltage_conv; + } + } + if(_isset(cs_p->pins[i])) channel_no++; + } + return 0; // pin not found +} + #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h index 7e74a96f..1294e8f1 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h @@ -7,8 +7,18 @@ #define _TRGO_NOT_AVAILABLE 12345 +// for searching the best ADCs, we need to know the number of ADCs +// it might be better to use some HAL variable for example ADC_COUNT +// here I've assumed the maximum number of ADCs is 5 +#define ADC_COUNT 5 + + #include "../../../common/foc_utils.h" #include "../../../communication/SimpleFOCDebug.h" +#include "../../../drivers/hardware_specific/stm32/stm32_mcu.h" +#include "stm32_mcu.h" + + /* Exported Functions */ /** @@ -34,5 +44,22 @@ int _adcToIndex(ADC_TypeDef *AdcHandle); int _findIndexOfFirstPinMapADCEntry(int pin); int _findIndexOfLastPinMapADCEntry(int pin); ADC_TypeDef* _findBestADCForPins(int num_pins, int pins[]); + + +// Structure to hold ADC interrupt configuration per ADC instance +struct Stm32AdcInterruptConfig { + bool needs_downsample = 0; + uint8_t tim_downsample = 0; + bool use_adc_interrupt = 0; +}; + +// returns 0 if no interrupt is needed, 1 if interrupt is needed +uint32_t _initTimerInterruptDownsampling(Stm32CurrentSenseParams* cs_params, STM32DriverParams* driver_params, Stm32AdcInterruptConfig& adc_interrupt_config); +// returns 0 if no downsampling is needed, 1 if downsampling is needed, 2 if error +uint8_t _handleInjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle, Stm32AdcInterruptConfig& adc_interrupt_config, uint32_t adc_val[4]); +// reads the ADC injected voltage for the given pin +// returns the voltage +// if the pin is not found in the current sense parameters, returns 0 +float _readADCInjectedChannelVoltage(int pin, void* cs_params, Stm32AdcInterruptConfig& adc_interrupt_config, uint32_t adc_val[4]); #endif #endif diff --git a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_mcu.cpp index 6d69dc89..7b0e9024 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_mcu.cpp @@ -13,19 +13,25 @@ #define _ADC_VOLTAGE_F1 3.3f #define _ADC_RESOLUTION_F1 4096.0f -// array of values of 4 injected channels per adc instance (3) -uint32_t adc_val[3][4]={0}; -// does adc interrupt need a downsample - per adc (3) -bool needs_downsample[3] = {1}; -// downsampling variable - per adc (3) -uint8_t tim_downsample[3] = {0}; +// array of values of 4 injected channels per adc instance (5) +uint32_t adc_val[5][4]={0}; #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT -uint8_t use_adc_interrupt = 1; +#define USE_ADC_INTERRUPT 1 #else -uint8_t use_adc_interrupt = 0; +#define USE_ADC_INTERRUPT 0 #endif +// structure containing the configuration of the adc interrupt +Stm32AdcInterruptConfig adc_interrupt_config[5] = { + {0, 0, USE_ADC_INTERRUPT}, // ADC1 + {0, 0, USE_ADC_INTERRUPT}, // ADC2 + {0, 0, USE_ADC_INTERRUPT}, // ADC3 + {0, 0, USE_ADC_INTERRUPT}, // ADC4 + {0, 0, USE_ADC_INTERRUPT} // ADC5 +}; + + void* _configureADCLowSide(const void* driver_params, const int pinA, const int pinB, const int pinC){ Stm32CurrentSenseParams* cs_params= new Stm32CurrentSenseParams { @@ -48,26 +54,15 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // stop all the timers for the driver stm32_pause(driver_params); - // if timer has repetition counter - it will downsample using it - // and it does not need the software downsample - if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){ - // adjust the initial timer state such that the trigger - // - for DMA transfer aligns with the pwm peaks instead of throughs. - // - for interrupt based ADC transfer - // - only necessary for the timers that have repetition counters - cs_params->timer_handle->Instance->CR1 |= TIM_CR1_DIR; - cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR; - // remember that this timer has repetition counter - no need to downasmple - needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0; - }else{ - if(!use_adc_interrupt){ - // If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing - use_adc_interrupt = 1; - #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used"); - #endif - } + // get the index of the adc + int adc_index = _adcToIndex(cs_params->adc_handle); + + bool tim_interrupt = _initTimerInterruptDownsampling(cs_params, driver_params, adc_interrupt_config[adc_index]); + if(tim_interrupt) { + // error in the timer interrupt initialization + SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used"); } + // set the trigger output event LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE); @@ -75,7 +70,7 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ HAL_ADCEx_Calibration_Start(cs_params->adc_handle); // start the adc - if(use_adc_interrupt){ + if(adc_interrupt_config[adc_index].use_adc_interrupt){ HAL_NVIC_SetPriority(ADC1_2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(ADC1_2_IRQn); @@ -97,37 +92,16 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ - uint8_t channel_no = 0; - for(int i=0; i < 3; i++){ - if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer - if (use_adc_interrupt){ - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - }else{ - // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = _getADCInjectedRank(channel_no); - return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - } - } - if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; - } - return 0; + uint8_t adc_index = (uint8_t)_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle); + return _readADCInjectedChannelVoltage(pin, (void*)cs_params, adc_interrupt_config[adc_index], adc_val[adc_index]); } extern "C" { void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){ - // calculate the instance - int adc_index = _adcToIndex(AdcHandle); - - // if the timer han't repetition counter - downsample two times - if( needs_downsample[adc_index] && tim_downsample[adc_index]++ > 0) { - tim_downsample[adc_index] = 0; - return; - } - - adc_val[adc_index][0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1); - adc_val[adc_index][1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2); - adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3); + uint8_t adc_index = (uint8_t)_adcToIndex(AdcHandle); + _handleInjectedConvCpltCallback(AdcHandle, adc_interrupt_config[adc_index], adc_val[adc_index]); } } + #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp index be49adfe..7bace501 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_mcu.cpp @@ -14,20 +14,24 @@ #define _ADC_VOLTAGE_F4 3.3f #define _ADC_RESOLUTION_F4 4096.0f - -// array of values of 4 injected channels per adc instance (3) -uint32_t adc_val[3][4]={0}; -// does adc interrupt need a downsample - per adc (3) -bool needs_downsample[3] = {1}; -// downsampling variable - per adc (3) -uint8_t tim_downsample[3] = {0}; - #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT -uint8_t use_adc_interrupt = 1; +#define USE_ADC_INTERRUPT 1 #else -uint8_t use_adc_interrupt = 0; +#define USE_ADC_INTERRUPT 0 #endif +// array of values of 4 injected channels per adc instance (5) +uint32_t adc_val[5][4]={0}; + +// structure containing the configuration of the adc interrupt +Stm32AdcInterruptConfig adc_interrupt_config[5] = { + {0, 0, USE_ADC_INTERRUPT}, // ADC1 + {0, 0, USE_ADC_INTERRUPT}, // ADC2 + {0, 0, USE_ADC_INTERRUPT}, // ADC3 + {0, 0, USE_ADC_INTERRUPT}, // ADC4 + {0, 0, USE_ADC_INTERRUPT} // ADC5 +}; + void* _configureADCLowSide(const void* driver_params, const int pinA, const int pinB, const int pinC){ Stm32CurrentSenseParams* cs_params= new Stm32CurrentSenseParams { @@ -50,31 +54,20 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // stop all the timers for the driver stm32_pause(driver_params); - // if timer has repetition counter - it will downsample using it - // and it does not need the software downsample - if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){ - // adjust the initial timer state such that the trigger - // - for DMA transfer aligns with the pwm peaks instead of throughs. - // - for interrupt based ADC transfer - // - only necessary for the timers that have repetition counters - cs_params->timer_handle->Instance->CR1 |= TIM_CR1_DIR; - cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR; - // remember that this timer has repetition counter - no need to downasmple - needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0; - }else{ - if(!use_adc_interrupt){ - // If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing - use_adc_interrupt = 1; - #ifdef SIMPLEFOC_STM32_DEBUG + // get the index of the adc + int adc_index = _adcToIndex(cs_params->adc_handle); + + bool tim_interrupt = _initTimerInterruptDownsampling(cs_params, driver_params, adc_interrupt_config[adc_index]); + if(tim_interrupt) { + // error in the timer interrupt initialization SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used"); - #endif - } } + // set the trigger output event LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE); // start the adc - if (use_adc_interrupt){ + if (adc_interrupt_config[adc_index].use_adc_interrupt){ // enable interrupt HAL_NVIC_SetPriority(ADC_IRQn, 0, 0); HAL_NVIC_EnableIRQ(ADC_IRQn); @@ -96,36 +89,14 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ - uint8_t channel_no = 0; - for(int i=0; i < 3; i++){ - if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer - if (use_adc_interrupt){ - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - }else{ - // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = _getADCInjectedRank(channel_no); - return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - } - } - if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; - } - return 0; + uint8_t adc_index = (uint8_t)_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle); + return _readADCInjectedChannelVoltage(pin, (void*)cs_params, adc_interrupt_config[adc_index], adc_val[adc_index]); } extern "C" { void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){ - // calculate the instance - int adc_index = _adcToIndex(AdcHandle); - - // if the timer han't repetition counter - downsample two times - if( needs_downsample[adc_index] && tim_downsample[adc_index]++ > 0) { - tim_downsample[adc_index] = 0; - return; - } - - adc_val[adc_index][0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1); - adc_val[adc_index][1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2); - adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3); + uint8_t adc_index = (uint8_t)_adcToIndex(AdcHandle); + _handleInjectedConvCpltCallback(AdcHandle, adc_interrupt_config[adc_index], adc_val[adc_index]); } } diff --git a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.cpp index ec5ccb64..595eb2a4 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_hal.cpp @@ -132,12 +132,6 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } } - #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT - // enable interrupt - HAL_NVIC_SetPriority(ADC_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(ADC_IRQn); - #endif - cs_params->adc_handle = &hadc; return 0; } @@ -174,13 +168,11 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int return 0; } -#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT extern "C" { void ADC_IRQHandler(void) { HAL_ADC_IRQHandler(&hadc); } } -#endif #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp index 664262dc..d8bac8d8 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f7/stm32f7_mcu.cpp @@ -14,13 +14,24 @@ #define _ADC_VOLTAGE 3.3f #define _ADC_RESOLUTION 4096.0f +// array of values of 4 injected channels per adc instance (5) +uint32_t adc_val[5][4]={0}; + +#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT +#define USE_ADC_INTERRUPT 1 +#else +#define USE_ADC_INTERRUPT 0 +#endif + +// structure containing the configuration of the adc interrupt +Stm32AdcInterruptConfig adc_interrupt_config[5] = { + {0, 0, USE_ADC_INTERRUPT}, // ADC1 + {0, 0, USE_ADC_INTERRUPT}, // ADC2 + {0, 0, USE_ADC_INTERRUPT}, // ADC3 + {0, 0, USE_ADC_INTERRUPT}, // ADC4 + {0, 0, USE_ADC_INTERRUPT} // ADC5 +}; -// array of values of 4 injected channels per adc instance (3) -uint32_t adc_val[3][4]={0}; -// does adc interrupt need a downsample - per adc (3) -bool needs_downsample[3] = {1}; -// downsampling variable - per adc (3) -uint8_t tim_downsample[3] = {1}; void* _configureADCLowSide(const void* driver_params, const int pinA, const int pinB, const int pinC){ @@ -44,28 +55,27 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // stop all the timers for the driver stm32_pause(driver_params); - // if timer has repetition counter - it will downsample using it - // and it does not need the software downsample - if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){ - // adjust the initial timer state such that the trigger - // - for DMA transfer aligns with the pwm peaks instead of throughs. - // - for interrupt based ADC transfer - // - only necessary for the timers that have repetition counters - - cs_params->timer_handle->Instance->CR1 |= TIM_CR1_DIR; - cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR; - // remember that this timer has repetition counter - no need to downasmple - needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0; + // get the index of the adc + int adc_index = _adcToIndex(cs_params->adc_handle); + + bool tim_interrupt = _initTimerInterruptDownsampling(cs_params, driver_params, adc_interrupt_config[adc_index]); + if(tim_interrupt) { + // error in the timer interrupt initialization + SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used"); } + // set the trigger output event LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE); // start the adc - #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT - HAL_ADCEx_InjectedStart_IT(cs_params->adc_handle); - #else - HAL_ADCEx_InjectedStart(cs_params->adc_handle); - #endif + if (adc_interrupt_config[adc_index].use_adc_interrupt){ + // enable interrupt + HAL_NVIC_SetPriority(ADC_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(ADC_IRQn); + HAL_ADCEx_InjectedStart_IT(cs_params->adc_handle); + }else{ + HAL_ADCEx_InjectedStart(cs_params->adc_handle); + } // restart all the timers of the driver stm32_resume(driver_params); @@ -79,40 +89,15 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ - uint8_t channel_no = 0; - for(int i=0; i < 3; i++){ - if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer - #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - #else - // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = _getADCInjectedRank(channel_no); - return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - #endif - } - if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; - } - return 0; + uint8_t adc_index = (uint8_t)_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle); + return _readADCInjectedChannelVoltage(pin, (void*)cs_params, adc_interrupt_config[adc_index], adc_val[adc_index]); } -#ifdef SIMPLEFOC_STM32_ADC_INTERRUPT extern "C" { void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){ - - // calculate the instance - int adc_index = _adcToIndex(AdcHandle); - - // if the timer han't repetition counter - downsample two times - if( needs_downsample[adc_index] && tim_downsample[adc_index]++ > 0) { - tim_downsample[adc_index] = 0; - return; - } - - adc_val[adc_index][0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1); - adc_val[adc_index][1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2); - adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3); + uint8_t adc_index = (uint8_t)_adcToIndex(AdcHandle); + _handleInjectedConvCpltCallback(AdcHandle, adc_interrupt_config[adc_index], adc_val[adc_index]); } } -#endif #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp index 5db5cea7..fd13e2b2 100644 --- a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp @@ -16,20 +16,25 @@ #define _ADC_VOLTAGE_G4 3.3f #define _ADC_RESOLUTION_G4 4096.0f - // array of values of 4 injected channels per adc instance (5) uint32_t adc_val[5][4]={0}; -// does adc interrupt need a downsample - per adc (5) -bool needs_downsample[5] = {1}; -// downsampling variable - per adc (5) -uint8_t tim_downsample[5] = {0}; #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT -uint8_t use_adc_interrupt = 1; +#define USE_ADC_INTERRUPT 1 #else -uint8_t use_adc_interrupt = 0; +#define USE_ADC_INTERRUPT 0 #endif +// structure containing the configuration of the adc interrupt +Stm32AdcInterruptConfig adc_interrupt_config[5] = { + {0, 0, USE_ADC_INTERRUPT}, // ADC1 + {0, 0, USE_ADC_INTERRUPT}, // ADC2 + {0, 0, USE_ADC_INTERRUPT}, // ADC3 + {0, 0, USE_ADC_INTERRUPT}, // ADC4 + {0, 0, USE_ADC_INTERRUPT} // ADC5 +}; + + void* _configureADCLowSide(const void* driver_params, const int pinA, const int pinB, const int pinC){ Stm32CurrentSenseParams* cs_params= new Stm32CurrentSenseParams { @@ -52,25 +57,13 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // stop all the timers for the driver stm32_pause(driver_params); - // if timer has repetition counter - it will downsample using it - // and it does not need the software downsample - if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){ - // adjust the initial timer state such that the trigger - // - for DMA transfer aligns with the pwm peaks instead of throughs. - // - for interrupt based ADC transfer - // - only necessary for the timers that have repetition counters - cs_params->timer_handle->Instance->CR1 |= TIM_CR1_DIR; - cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR; - // remember that this timer has repetition counter - no need to downasmple - needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0; - }else{ - if(!use_adc_interrupt){ - // If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing - use_adc_interrupt = 1; - #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used"); - #endif - } + // get the index of the adc + int adc_index = _adcToIndex(cs_params->adc_handle); + + bool tim_interrupt = _initTimerInterruptDownsampling(cs_params, driver_params, adc_interrupt_config[adc_index]); + if(tim_interrupt) { + // error in the timer interrupt initialization + SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used"); } // set the trigger output event @@ -80,7 +73,7 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ HAL_ADCEx_Calibration_Start(cs_params->adc_handle, ADC_SINGLE_ENDED); // start the adc - if (use_adc_interrupt){ + if (adc_interrupt_config[adc_index].use_adc_interrupt){ // enable interrupt if(cs_params->adc_handle->Instance == ADC1) { // enable interrupt @@ -133,37 +126,14 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ - uint8_t channel_no = 0; - for(int i=0; i < 3; i++){ - if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer - if (use_adc_interrupt){ - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - }else{ - // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = _getADCInjectedRank(channel_no); - return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - } - } - if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; - } - return 0; + uint8_t adc_index = (uint8_t)_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle); + return _readADCInjectedChannelVoltage(pin, (void*)cs_params, adc_interrupt_config[adc_index], adc_val[adc_index]); } extern "C" { void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){ - // calculate the instance - int adc_index = _adcToIndex(AdcHandle); - - // if the timer han't repetition counter - downsample two times - if( needs_downsample[adc_index] && tim_downsample[adc_index]++ > 0) { - tim_downsample[adc_index] = 0; - return; - } - - adc_val[adc_index][0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1); - adc_val[adc_index][1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2); - adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3); - adc_val[adc_index][3]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_4); + uint8_t adc_index = (uint8_t)_adcToIndex(AdcHandle); + _handleInjectedConvCpltCallback(AdcHandle, adc_interrupt_config[adc_index], adc_val[adc_index]); } } diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp index 61ae2de3..0ad49cb9 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp @@ -59,7 +59,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L170C13-L170C27 hadc.Init.DMAContinuousRequests = DISABLE; // not sure about this one!!! maybe use: ADC_SAMPLING_MODE_NORMAL - hadc.Init.SamplingMode = ADC_SAMPLING_MODE_BULB; + hadc.Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL; #endif hadc.Init.NbrOfConversion = 1; hadc.Init.NbrOfDiscConversion = 0; @@ -86,7 +86,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive // if ADC1 or ADC2 if(hadc.Instance == ADC1 || hadc.Instance == ADC2){ // more info here: https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L658 - sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_1CYCLE_5; + sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_2CYCLES_5; }else { // adc3 // https://github.com/stm32duino/Arduino_Core_STM32/blob/e156c32db24d69cb4818208ccc28894e2f427cfa/system/Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_adc.h#L673 @@ -152,13 +152,6 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive return -1; } } - - delay(1000); - #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT - // enable interrupt - HAL_NVIC_SetPriority(ADC_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(ADC_IRQn); - #endif cs_params->adc_handle = &hadc; return 0; @@ -204,4 +197,13 @@ extern "C" { } } +#ifdef ADC3 +extern "C" { + void ADC3_IRQHandler(void) + { + HAL_ADC_IRQHandler(&hadc); + } +} +#endif + #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp index f826e69d..31f2c16b 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_mcu.cpp @@ -15,19 +15,25 @@ #define _ADC_RESOLUTION 4096.0f -// array of values of 4 injected channels per adc instance (3) -uint32_t adc_val[3][4]={0}; -// does adc interrupt need a downsample - per adc (3) -bool needs_downsample[3] = {1}; -// downsampling variable - per adc (3) -uint8_t tim_downsample[3] = {1}; +// array of values of 4 injected channels per adc instance (5) +uint32_t adc_val[5][4]={0}; #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT -uint8_t use_adc_interrupt = 1; +#define USE_ADC_INTERRUPT 1 #else -uint8_t use_adc_interrupt = 0; +#define USE_ADC_INTERRUPT 0 #endif +// structure containing the configuration of the adc interrupt +Stm32AdcInterruptConfig adc_interrupt_config[5] = { + {0, 0, USE_ADC_INTERRUPT}, // ADC1 + {0, 0, USE_ADC_INTERRUPT}, // ADC2 + {0, 0, USE_ADC_INTERRUPT}, // ADC3 + {0, 0, USE_ADC_INTERRUPT}, // ADC4 + {0, 0, USE_ADC_INTERRUPT} // ADC5 +}; + + void* _configureADCLowSide(const void* driver_params, const int pinA, const int pinB, const int pinC){ Stm32CurrentSenseParams* cs_params= new Stm32CurrentSenseParams { @@ -50,27 +56,14 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // stop all the timers for the driver stm32_pause(driver_params); - // if timer has repetition counter - it will downsample using it - // and it does not need the software downsample - if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){ - // adjust the initial timer state such that the trigger - // - for DMA transfer aligns with the pwm peaks instead of throughs. - // - for interrupt based ADC transfer - // - only necessary for the timers that have repetition counters - - cs_params->timer_handle->Instance->CR1 |= TIM_CR1_DIR; - cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR; - // remember that this timer has repetition counter - no need to downasmple - needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0; - }else{ - if(!use_adc_interrupt){ - // If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing - use_adc_interrupt = 1; - #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used"); - #endif - } + // get the index of the adc + int adc_index = _adcToIndex(cs_params->adc_handle); + bool tim_interrupt = _initTimerInterruptDownsampling(cs_params, driver_params, adc_interrupt_config[adc_index]); + if(tim_interrupt) { + // error in the timer interrupt initialization + SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used"); } + // set the trigger output event LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE); @@ -84,17 +77,33 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ } // start the adc - if(use_adc_interrupt){ - // enable interrupt - HAL_NVIC_SetPriority(ADC_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(ADC_IRQn); - - if(HAL_ADCEx_InjectedStart_IT(cs_params->adc_handle) != HAL_OK){ - #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot start injected channels in interrupt mode!"); - #endif - return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED; + if(adc_interrupt_config[adc_index].use_adc_interrupt){ + + if(cs_params->adc_handle->Instance == ADC1){ + // enable interrupt + HAL_NVIC_SetPriority(ADC_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(ADC_IRQn); } + #ifdef ADC2 // if defined ADC2 + else if(cs_params->adc_handle->Instance == ADC2) { + // enable interrupt + HAL_NVIC_SetPriority(ADC3_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(ADC3_IRQn); + } + #endif + #ifdef ADC3 // if defined ADC3 + else if(cs_params->adc_handle->Instance == ADC3) { + // enable interrupt + HAL_NVIC_SetPriority(ADC3_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(ADC3_IRQn); + } + #endif + if(HAL_ADCEx_InjectedStart_IT(cs_params->adc_handle) != HAL_OK){ + #ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot start injected channels in interrupt mode!"); + #endif + return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED; + } }else{ if(HAL_ADCEx_InjectedStart(cs_params->adc_handle) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG @@ -117,40 +126,14 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ - // print all values in the buffer - // SIMPLEFOC_DEBUG("adc_a:", (int)HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, _getADCInjectedRank(0))); - // SIMPLEFOC_DEBUG("adc_b:", (int)HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, _getADCInjectedRank(1))); - uint8_t channel_no = 0; - for(int i=0; i < 3; i++){ - if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer - if (use_adc_interrupt){ - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - }else{ - // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = _getADCInjectedRank(channel_no); - return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle, channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - } - } - if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; - } - return 0; + uint8_t adc_index = (uint8_t)_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle); + return _readADCInjectedChannelVoltage(pin, (void*)cs_params, adc_interrupt_config[adc_index], adc_val[adc_index]); } extern "C" { void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){ - - // calculate the instance - int adc_index = _adcToIndex(AdcHandle); - - // if the timer han't repetition counter - downsample two times - if( needs_downsample[adc_index] && tim_downsample[adc_index]++ > 1) { - tim_downsample[adc_index] = 1; - return; - } - - adc_val[adc_index][0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1); - adc_val[adc_index][1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2); - adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3); + uint8_t adc_index = (uint8_t)_adcToIndex(AdcHandle); + _handleInjectedConvCpltCallback(AdcHandle, adc_interrupt_config[adc_index], adc_val[adc_index]); } } diff --git a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp index 4a6e529c..9bd4a33f 100644 --- a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_mcu.cpp @@ -18,17 +18,22 @@ // array of values of 4 injected channels per adc instance (5) uint32_t adc_val[5][4]={0}; -// does adc interrupt need a downsample - per adc (5) -bool needs_downsample[5] = {1}; -// downsampling variable - per adc (5) -uint8_t tim_downsample[5] = {0}; #ifdef SIMPLEFOC_STM32_ADC_INTERRUPT -uint8_t use_adc_interrupt = 1; +#define USE_ADC_INTERRUPT 1 #else -uint8_t use_adc_interrupt = 0; +#define USE_ADC_INTERRUPT 0 #endif +// structure containing the configuration of the adc interrupt +Stm32AdcInterruptConfig adc_interrupt_config[5] = { + {0, 0, USE_ADC_INTERRUPT}, // ADC1 + {0, 0, USE_ADC_INTERRUPT}, // ADC2 + {0, 0, USE_ADC_INTERRUPT}, // ADC3 + {0, 0, USE_ADC_INTERRUPT}, // ADC4 + {0, 0, USE_ADC_INTERRUPT} // ADC5 +}; + void* _configureADCLowSide(const void* driver_params, const int pinA, const int pinB, const int pinC){ Stm32CurrentSenseParams* cs_params= new Stm32CurrentSenseParams { @@ -51,27 +56,16 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // stop all the timers for the driver stm32_pause(driver_params); - // if timer has repetition counter - it will downsample using it - // and it does not need the software downsample - if( IS_TIM_REPETITION_COUNTER_INSTANCE(cs_params->timer_handle->Instance) ){ - // adjust the initial timer state such that the trigger - // - for DMA transfer aligns with the pwm peaks instead of throughs. - // - for interrupt based ADC transfer - // - only necessary for the timers that have repetition counters - cs_params->timer_handle->Instance->CR1 |= TIM_CR1_DIR; - cs_params->timer_handle->Instance->CNT = cs_params->timer_handle->Instance->ARR; - // remember that this timer has repetition counter - no need to downasmple - needs_downsample[_adcToIndex(cs_params->adc_handle)] = 0; - }else{ - if(!use_adc_interrupt){ - // If the timer has no repetition counter, it needs to use the interrupt to downsample for low side sensing - use_adc_interrupt = 1; - #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used"); - #endif - } + // get the index of the adc + int adc_index = _adcToIndex(cs_params->adc_handle); + + bool tim_interrupt = _initTimerInterruptDownsampling(cs_params, driver_params, adc_interrupt_config[adc_index]); + if(tim_interrupt) { + // error in the timer interrupt initialization + SIMPLEFOC_DEBUG("STM32-CS: timer has no repetition counter, ADC interrupt has to be used"); } + // set the trigger output event LL_TIM_SetTriggerOutput(cs_params->timer_handle->Instance, LL_TIM_TRGO_UPDATE); @@ -79,7 +73,7 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ HAL_ADCEx_Calibration_Start(cs_params->adc_handle,ADC_SINGLE_ENDED); // start the adc - if (use_adc_interrupt){ + if (adc_interrupt_config[adc_index].use_adc_interrupt){ if(cs_params->adc_handle->Instance == ADC1) { // enable interrupt HAL_NVIC_SetPriority(ADC1_2_IRQn, 0, 0); @@ -125,40 +119,17 @@ void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ // TODO verify if success in future return _cs_params; } - // function reading an ADC value and returning the read voltage float _readADCVoltageLowSide(const int pin, const void* cs_params){ - uint8_t channel_no = 0; - for(int i=0; i < 3; i++){ - if( pin == ((Stm32CurrentSenseParams*)cs_params)->pins[i]){ // found in the buffer - if (use_adc_interrupt){ - return adc_val[_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle)][channel_no] * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - }else{ - // an optimized way to go from i to the channel i=0 -> channel 1, i=1 -> channel 2, i=2 -> channel 3 - uint32_t channel = _getADCInjectedRank(channel_no); - return HAL_ADCEx_InjectedGetValue(((Stm32CurrentSenseParams*)cs_params)->adc_handle,channel) * ((Stm32CurrentSenseParams*)cs_params)->adc_voltage_conv; - } - } - if(_isset(((Stm32CurrentSenseParams*)cs_params)->pins[i])) channel_no++; - } - return 0; + uint8_t adc_index = (uint8_t)_adcToIndex(((Stm32CurrentSenseParams*)cs_params)->adc_handle); + return _readADCInjectedChannelVoltage(pin, (void*)cs_params, adc_interrupt_config[adc_index], adc_val[adc_index]); } extern "C" { void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){ - // calculate the instance - int adc_index = _adcToIndex(AdcHandle); - - // if the timer han't repetition counter - downsample two times - if( needs_downsample[adc_index] && tim_downsample[adc_index]++ > 0) { - tim_downsample[adc_index] = 0; - return; - } - - adc_val[adc_index][0]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_1); - adc_val[adc_index][1]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_2); - adc_val[adc_index][2]=HAL_ADCEx_InjectedGetValue(AdcHandle, ADC_INJECTED_RANK_3); + uint8_t adc_index = (uint8_t)_adcToIndex(AdcHandle); + _handleInjectedConvCpltCallback(AdcHandle, adc_interrupt_config[adc_index], adc_val[adc_index]); } }