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 8df30a60..bf9a210d 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.cpp @@ -115,9 +115,9 @@ int _findIndexOfLastPinMapADCEntry(int pin) { // each pin can be connected to multiple ADCs // the function will try to find a single ADC that can be used for all pins // if not possible it will return nullptr -ADC_TypeDef* _findBestADCForPins(int numPins, int pins[]) { +ADC_TypeDef* _findBestADCForPins(int numPins, int pins[], ADC_HandleTypeDef adc_handles[]) { - // assuning that there is less than 8 ADCs + // assuning that there is at most 5 ADCs uint8_t pins_at_adc[ADC_COUNT] = {0}; // check how many pins are there and are not set @@ -152,11 +152,19 @@ ADC_TypeDef* _findBestADCForPins(int numPins, int pins[]) { SimpleFOCDebug::print(i+1); SimpleFOCDebug::print(" pins: "); SimpleFOCDebug::println(pins_at_adc[i]); + if (adc_handles[i].Instance != NP) { + SimpleFOCDebug::print("STM32-CS: ADC"); + SimpleFOCDebug::print(i+1); + SimpleFOCDebug::println(" already in use!"); + } } #endif // now take the first ADC that has all pins connected for (int i = 0; i < ADC_COUNT; i++) { + if (adc_handles[i].Instance != NP) { + continue; // ADC already in use + } if (pins_at_adc[i] == no_pins) { return _indexToADC(i); } 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 1294e8f1..3e15976e 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h +++ b/src/current_sense/hardware_specific/stm32/stm32_adc_utils.h @@ -18,8 +18,6 @@ #include "../../../drivers/hardware_specific/stm32/stm32_mcu.h" #include "stm32_mcu.h" - - /* Exported Functions */ /** * @brief Return ADC HAL channel linked to a PinName @@ -43,7 +41,7 @@ int _adcToIndex(ADC_TypeDef *AdcHandle); // functions helping to find the best ADC channel int _findIndexOfFirstPinMapADCEntry(int pin); int _findIndexOfLastPinMapADCEntry(int pin); -ADC_TypeDef* _findBestADCForPins(int num_pins, int pins[]); +ADC_TypeDef* _findBestADCForPins(int num_pins, int pins[], ADC_HandleTypeDef adc_handles[]); // Structure to hold ADC interrupt configuration per ADC instance diff --git a/src/current_sense/hardware_specific/stm32/stm32_mcu.cpp b/src/current_sense/hardware_specific/stm32/stm32_mcu.cpp index efc55733..a519c1a0 100644 --- a/src/current_sense/hardware_specific/stm32/stm32_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32_mcu.cpp @@ -9,7 +9,7 @@ #define _ADC_RESOLUTION 1024.0f // function reading an ADC value and returning the read voltage -void* _configureADCInline(const void* driver_params, const int pinA,const int pinB,const int pinC){ +__attribute__((weak)) void* _configureADCInline(const void* driver_params, const int pinA,const int pinB,const int pinC){ _UNUSED(driver_params); if( _isset(pinA) ) pinMode(pinA, INPUT); diff --git a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp index 8e5d551d..e65c99e5 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f1/stm32f1_hal.cpp @@ -4,9 +4,9 @@ #include "../../../../communication/SimpleFOCDebug.h" #include "../stm32_adc_utils.h" -#define _TRGO_NOT_AVAILABLE 12345 -ADC_HandleTypeDef hadc; +// pointer to the ADC handles used in the project +ADC_HandleTypeDef hadc[ADC_COUNT] = {0}; /** * Function initializing the ADC and the injected channels for the low-side current sensing @@ -22,14 +22,14 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = _findBestADCForPins(3, cs_params->pins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); - if(hadc.Instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); + if(adc_instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 - else if(hadc.Instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); + else if(adc_instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); #endif #ifdef ADC3 // if defined ADC3 - else if(hadc.Instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); + else if(adc_instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); #endif else{ #ifdef SIMPLEFOC_STM32_DEBUG @@ -38,13 +38,15 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive return -1; // error not a valid ADC instance } - hadc.Init.ScanConvMode = ADC_SCAN_ENABLE; - hadc.Init.ContinuousConvMode = ENABLE; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; - hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc.Init.NbrOfConversion = 1; - HAL_ADC_Init(&hadc); + auto adc_num = _adcToIndex(adc_instance); + hadc[adc_num].Instance = adc_instance; + hadc[adc_num].Init.ScanConvMode = ADC_SCAN_ENABLE; + hadc[adc_num].Init.ContinuousConvMode = ENABLE; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; + hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc[adc_num].Init.NbrOfConversion = 1; + HAL_ADC_Init(&hadc[adc_num]); /**Configure for the selected ADC regular channel to be converted. */ @@ -102,15 +104,15 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; return 0; } @@ -149,8 +151,18 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC1_2_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[0].Instance != NP) + HAL_ADC_IRQHandler(&hadc[0]); + if (hadc[1].Instance != NP) + HAL_ADC_IRQHandler(&hadc[1]); } +#ifdef ADC3 + void ADC3_IRQHandler(void) + { + if (hadc[2].Instance != NP) + HAL_ADC_IRQHandler(&hadc[2]); + } +#endif } #endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.cpp index 7fd188dd..b8c3bf33 100644 --- a/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32f4/stm32f4_hal.cpp @@ -5,9 +5,9 @@ //#define SIMPLEFOC_STM32_DEBUG #include "../../../../communication/SimpleFOCDebug.h" -#define _TRGO_NOT_AVAILABLE 12345 -ADC_HandleTypeDef hadc; +// pointer to the ADC handles used in the project +ADC_HandleTypeDef hadc[ADC_COUNT] = {0}; /** * Function initializing the ADC and the injected channels for the low-side current sensing @@ -23,14 +23,14 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = _findBestADCForPins(3, cs_params->pins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); - if(hadc.Instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); + if(adc_instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 - else if(hadc.Instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); + else if(adc_instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); #endif #ifdef ADC3 // if defined ADC3 - else if(hadc.Instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); + else if(adc_instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); #endif else{ #ifdef SIMPLEFOC_STM32_DEBUG @@ -39,22 +39,26 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive return -1; // error not a valid ADC instance } + int adc_num = _adcToIndex(adc_instance); + #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", _adcToIndex(&hadc)+1); + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1); #endif - hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; - hadc.Init.Resolution = ADC_RESOLUTION_12B; - hadc.Init.ScanConvMode = ENABLE; - hadc.Init.ContinuousConvMode = ENABLE; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now - hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc.Init.NbrOfConversion = 1; - hadc.Init.DMAContinuousRequests = DISABLE; - hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; - if ( HAL_ADC_Init(&hadc) != HAL_OK){ + hadc[adc_num].Instance = adc_instance; + + hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; + hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B; + hadc[adc_num].Init.ScanConvMode = ENABLE; + hadc[adc_num].Init.ContinuousConvMode = ENABLE; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now + hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc[adc_num].Init.NbrOfConversion = 1; + hadc[adc_num].Init.DMAContinuousRequests = DISABLE; + hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV; + if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); #endif @@ -115,15 +119,15 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; return 0; } @@ -160,7 +164,10 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + for(int adc_num=0; adc_numpins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); - if(hadc.Instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); + if(adc_instance == ADC1) __HAL_RCC_ADC1_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 - else if(hadc.Instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); + else if(adc_instance == ADC2) __HAL_RCC_ADC2_CLK_ENABLE(); #endif #ifdef ADC3 // if defined ADC3 - else if(hadc.Instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); + else if(adc_instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); #endif else{ #ifdef SIMPLEFOC_STM32_DEBUG @@ -38,23 +38,26 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif return -1; // error not a valid ADC instance } + + int adc_num = _adcToIndex(adc_instance); #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", _adcToIndex(&hadc)+1); + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1); #endif - hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; - hadc.Init.Resolution = ADC_RESOLUTION_12B; - hadc.Init.ScanConvMode = ENABLE; - hadc.Init.ContinuousConvMode = DISABLE; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now - hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc.Init.NbrOfConversion = 1; - hadc.Init.DMAContinuousRequests = DISABLE; - hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; - if ( HAL_ADC_Init(&hadc) != HAL_OK){ + hadc[adc_num].Instance = adc_instance; + hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; + hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B; + hadc[adc_num].Init.ScanConvMode = ENABLE; + hadc[adc_num].Init.ContinuousConvMode = DISABLE; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now + hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc[adc_num].Init.NbrOfConversion = 1; + hadc[adc_num].Init.DMAContinuousRequests = DISABLE; + hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV; + if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); #endif @@ -123,16 +126,16 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; return 0; } @@ -172,7 +175,10 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + for(int adc_num=0; adc_numpins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); - if(hadc.Instance == ADC1) { + if(adc_instance == ADC1) { #ifdef __HAL_RCC_ADC1_CLK_ENABLE __HAL_RCC_ADC1_CLK_ENABLE(); #endif @@ -33,7 +35,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif } #ifdef ADC2 - else if (hadc.Instance == ADC2) { + else if (adc_instance == ADC2) { #ifdef __HAL_RCC_ADC2_CLK_ENABLE __HAL_RCC_ADC2_CLK_ENABLE(); #endif @@ -43,7 +45,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC3 - else if (hadc.Instance == ADC3) { + else if (adc_instance == ADC3) { #ifdef __HAL_RCC_ADC3_CLK_ENABLE __HAL_RCC_ADC3_CLK_ENABLE(); #endif @@ -56,7 +58,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC4 - else if (hadc.Instance == ADC4) { + else if (adc_instance == ADC4) { #ifdef __HAL_RCC_ADC4_CLK_ENABLE __HAL_RCC_ADC4_CLK_ENABLE(); #endif @@ -69,7 +71,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC5 - else if (hadc.Instance == ADC5) { + else if (adc_instance == ADC5) { #if defined(ADC345_COMMON) __HAL_RCC_ADC345_CLK_ENABLE(); #endif @@ -82,26 +84,29 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive return -1; // error not a valid ADC instance } + int adc_num = _adcToIndex(adc_instance); + #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", _adcToIndex(&hadc)+1); -#endif - - - hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; - hadc.Init.Resolution = ADC_RESOLUTION_12B; - hadc.Init.ScanConvMode = ADC_SCAN_ENABLE; - hadc.Init.ContinuousConvMode = DISABLE; - hadc.Init.LowPowerAutoWait = DISABLE; - hadc.Init.GainCompensation = 0; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now - hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc.Init.NbrOfConversion = 1; - hadc.Init.DMAContinuousRequests = DISABLE; - hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; - hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED; - if ( HAL_ADC_Init(&hadc) != HAL_OK){ + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1); +#endif + + hadc[adc_num].Instance = adc_instance; + + hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; + hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B; + hadc[adc_num].Init.ScanConvMode = ADC_SCAN_ENABLE; + hadc[adc_num].Init.ContinuousConvMode = DISABLE; + hadc[adc_num].Init.LowPowerAutoWait = DISABLE; + hadc[adc_num].Init.GainCompensation = 0; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now + hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc[adc_num].Init.NbrOfConversion = 1; + hadc[adc_num].Init.DMAContinuousRequests = DISABLE; + hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV; + hadc[adc_num].Init.Overrun = ADC_OVR_DATA_PRESERVED; + if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); #endif @@ -166,15 +171,175 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; + return 0; +} + +/** + * Function initializing the ADC and the regular channels for inline current sensing + * with continuous conversion mode + * + * @param cs_params - current sense parameters + * + * @return int - 0 if success + */ +int _adc_init_inline(Stm32CurrentSenseParams* cs_params) +{ + ADC_ChannelConfTypeDef sConfig = {0}; + + /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) + */ + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); + + if(adc_instance == ADC1) { +#ifdef __HAL_RCC_ADC1_CLK_ENABLE + __HAL_RCC_ADC1_CLK_ENABLE(); +#endif +#ifdef __HAL_RCC_ADC12_CLK_ENABLE + __HAL_RCC_ADC12_CLK_ENABLE(); +#endif + } +#ifdef ADC2 + else if (adc_instance == ADC2) { +#ifdef __HAL_RCC_ADC2_CLK_ENABLE + __HAL_RCC_ADC2_CLK_ENABLE(); +#endif +#ifdef __HAL_RCC_ADC12_CLK_ENABLE + __HAL_RCC_ADC12_CLK_ENABLE(); +#endif + } +#endif +#ifdef ADC3 + else if (adc_instance == ADC3) { +#ifdef __HAL_RCC_ADC3_CLK_ENABLE + __HAL_RCC_ADC3_CLK_ENABLE(); +#endif +#ifdef __HAL_RCC_ADC34_CLK_ENABLE + __HAL_RCC_ADC34_CLK_ENABLE(); +#endif +#if defined(ADC345_COMMON) + __HAL_RCC_ADC345_CLK_ENABLE(); +#endif + } +#endif +#ifdef ADC4 + else if (adc_instance == ADC4) { +#ifdef __HAL_RCC_ADC4_CLK_ENABLE + __HAL_RCC_ADC4_CLK_ENABLE(); +#endif +#ifdef __HAL_RCC_ADC34_CLK_ENABLE + __HAL_RCC_ADC34_CLK_ENABLE(); +#endif +#if defined(ADC345_COMMON) + __HAL_RCC_ADC345_CLK_ENABLE(); +#endif + } +#endif +#ifdef ADC5 + else if (adc_instance == ADC5) { +#if defined(ADC345_COMMON) + __HAL_RCC_ADC345_CLK_ENABLE(); +#endif + } +#endif + else{ +#ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: Cannot find a common ADC for the pins!"); +#endif + return -1; // error not a valid ADC instance + } + + int adc_num = _adcToIndex(adc_instance); + +#ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1); +#endif + + hadc[adc_num].Instance = adc_instance; + + // Configure ADC for continuous conversion mode on regular channels + hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; + hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B; + hadc[adc_num].Init.ScanConvMode = ADC_SCAN_ENABLE; // Enable scan mode for multiple channels + hadc[adc_num].Init.ContinuousConvMode = ENABLE; // Enable continuous conversion + hadc[adc_num].Init.LowPowerAutoWait = DISABLE; + hadc[adc_num].Init.GainCompensation = 0; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; + hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT; + + // Count number of channels to configure + uint8_t num_channels = 0; + for(int pin_no=0; pin_no<3; pin_no++){ + if(_isset(cs_params->pins[pin_no])){ + num_channels++; + } + } + + hadc[adc_num].Init.NbrOfConversion = num_channels; + hadc[adc_num].Init.DMAContinuousRequests = DISABLE; + hadc[adc_num].Init.EOCSelection = ADC_EOC_SEQ_CONV; // End of sequence for multi-channel + hadc[adc_num].Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; // Overwrite old data in continuous mode + + if (HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){ +#ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); +#endif + return -1; + } + + // Configure regular channels + sConfig.SamplingTime = ADC_SAMPLETIME_6CYCLES_5; // Fast sampling for inline sensing + sConfig.SingleDiff = ADC_SINGLE_ENDED; + sConfig.OffsetNumber = ADC_OFFSET_NONE; + sConfig.Offset = 0; + + uint8_t rank = 1; + for(int i=0; i<3; i++){ + // skip if not set + if (!_isset(cs_params->pins[i])) continue; + + sConfig.Rank = rank++; + sConfig.Channel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + + if (HAL_ADC_ConfigChannel(&hadc[adc_num], &sConfig) != HAL_OK){ + #ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init regular channel: ", (int)sConfig.Channel); + #endif + return -1; + } + } + + cs_params->adc_handle = &hadc[adc_num]; + + // Calibrate ADC + if (HAL_ADCEx_Calibration_Start(&hadc[adc_num], ADC_SINGLE_ENDED) != HAL_OK){ +#ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: WARN: ADC calibration failed"); +#endif + } + + // Start continuous conversion + if (HAL_ADC_Start(&hadc[adc_num]) != HAL_OK){ +#ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot start ADC continuous conversion"); +#endif + return -1; + } + +#ifdef SIMPLEFOC_STM32_DEBUG + SIMPLEFOC_DEBUG("STM32-CS: ADC continuous conversion on no.channels: ", (int)num_channels); +#endif + return 0; } @@ -214,26 +379,32 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC1_2_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[0].Instance != NP) + HAL_ADC_IRQHandler(&hadc[0]); + if (hadc[1].Instance != NP) + HAL_ADC_IRQHandler(&hadc[1]); } #ifdef ADC3 void ADC3_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[2].Instance != NP) + HAL_ADC_IRQHandler(&hadc[2]); } #endif #ifdef ADC4 void ADC4_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[3].Instance != NP) + HAL_ADC_IRQHandler(&hadc[3]); } #endif #ifdef ADC5 void ADC5_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[4].Instance != NP) + HAL_ADC_IRQHandler(&hadc[4]); } #endif } diff --git a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.h b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.h index 81faf26b..b43eb61f 100644 --- a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.h +++ b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_hal.h @@ -10,6 +10,7 @@ #include "../stm32_adc_utils.h" int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* driver_params); +int _adc_init_inline(Stm32CurrentSenseParams* cs_params); int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int pinB, const int pinC); #endif 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 68b50148..dcac71c1 100644 --- a/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32g4/stm32g4_mcu.cpp @@ -46,6 +46,20 @@ void* _configureADCLowSide(const void* driver_params, const int pinA, const int return cs_params; } +void* _configureADCInline(const void* driver_params, const int pinA, const int pinB, const int pinC){ + _UNUSED(driver_params); + + Stm32CurrentSenseParams* cs_params = new Stm32CurrentSenseParams { + .pins={(int)NOT_SET, (int)NOT_SET, (int)NOT_SET}, + .adc_voltage_conv = (_ADC_VOLTAGE_G4) / (_ADC_RESOLUTION_G4) + }; + + if(_adc_gpio_init(cs_params, pinA, pinB, pinC) != 0) return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED; + if(_adc_init_inline(cs_params) != 0) return SIMPLEFOC_CURRENT_SENSE_INIT_FAILED; + + return cs_params; +} + void* _driverSyncLowSide(void* _driver_params, void* _cs_params){ STM32DriverParams* driver_params = (STM32DriverParams*)_driver_params; @@ -131,6 +145,19 @@ float _readADCVoltageLowSide(const int pin, const void* cs_params){ return _readADCInjectedChannelVoltage(pin, (void*)cs_params, adc_interrupt_config[adc_index], adc_val[adc_index]); } +// function reading an ADC value from regular channels (inline current sensing) +float _readADCVoltageInline(const int pin, const void* cs_params){ + Stm32CurrentSenseParams* params = (Stm32CurrentSenseParams*)cs_params; + ADC_HandleTypeDef* hadc = params->adc_handle; + + // In continuous conversion mode, just read the latest value from the data register + // No polling needed - the ADC is constantly updating this register + uint32_t raw_adc = HAL_ADC_GetValue(hadc); + + // Convert to voltage + return raw_adc * params->adc_voltage_conv; +} + extern "C" { void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *AdcHandle){ uint8_t adc_index = (uint8_t)_adcToIndex(AdcHandle); 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 e1b5cfde..8259f960 100644 --- a/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32h7/stm32h7_hal.cpp @@ -6,7 +6,8 @@ #include "../../../../communication/SimpleFOCDebug.h" -ADC_HandleTypeDef hadc; +// pointer to the ADC handles used in the project +ADC_HandleTypeDef hadc[ADC_COUNT] = {0}; /** * Function initializing the ADC and the injected channels for the low-side current sensing @@ -23,14 +24,14 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = _findBestADCForPins(3, cs_params->pins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); - if(hadc.Instance == ADC1) __HAL_RCC_ADC12_CLK_ENABLE(); + if(adc_instance == ADC1) __HAL_RCC_ADC12_CLK_ENABLE(); #ifdef ADC2 // if defined ADC2 - else if(hadc.Instance == ADC2) __HAL_RCC_ADC12_CLK_ENABLE(); + else if(adc_instance == ADC2) __HAL_RCC_ADC12_CLK_ENABLE(); #endif #ifdef ADC3 // if defined ADC3 - else if(hadc.Instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); + else if(adc_instance == ADC3) __HAL_RCC_ADC3_CLK_ENABLE(); #endif else{ #ifdef SIMPLEFOC_STM32_DEBUG @@ -39,36 +40,39 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive return -1; // error not a valid ADC instance } + int adc_num = _adcToIndex(adc_instance); + #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", _adcToIndex(&hadc)+1); + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1); #endif - hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; - hadc.Init.Resolution = ADC_RESOLUTION_12B; - hadc.Init.ScanConvMode = ENABLE; - hadc.Init.ContinuousConvMode = DISABLE; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now + hadc[adc_num].Instance = adc_instance; + hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; + hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B; + hadc[adc_num].Init.ScanConvMode = ENABLE; + hadc[adc_num].Init.ContinuousConvMode = DISABLE; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now #if defined(ADC_VER_V5_V90) // only for ADC3 - if(hadc.Instance == ADC3){ - hadc.Init.DataAlign = ADC3_DATAALIGN_RIGHT; + if(hadc[adc_num].Instance == ADC3){ + hadc[adc_num].Init.DataAlign = ADC3_DATAALIGN_RIGHT; } // more info here // 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; + hadc[adc_num].Init.DMAContinuousRequests = DISABLE; // not sure about this one!!! maybe use: ADC_SAMPLING_MODE_NORMAL - hadc.Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL; + hadc[adc_num].Init.SamplingMode = ADC_SAMPLING_MODE_NORMAL; #endif - hadc.Init.NbrOfConversion = 1; - hadc.Init.NbrOfDiscConversion = 0; - hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; + hadc[adc_num].Init.NbrOfConversion = 1; + hadc[adc_num].Init.NbrOfDiscConversion = 0; + hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV; - hadc.Init.LowPowerAutoWait = DISABLE; + hadc[adc_num].Init.LowPowerAutoWait = DISABLE; - if ( HAL_ADC_Init(&hadc) != HAL_OK){ + if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); #endif @@ -84,7 +88,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } } // if ADC1 or ADC2 - if(hadc.Instance == ADC1 || hadc.Instance == ADC2){ + if(hadc[adc_num].Instance == ADC1 || hadc[adc_num].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_2CYCLES_5; }else { @@ -144,16 +148,16 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]) , hadc[adc_num].Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; return 0; } @@ -194,14 +198,18 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[0].Instance != NP) + HAL_ADC_IRQHandler(&hadc[0]); + if (hadc[1].Instance != NP) + HAL_ADC_IRQHandler(&hadc[1]); } } #ifdef ADC3 extern "C" { void ADC3_IRQHandler(void) - { + { + if (hadc[2].Instance != NP) HAL_ADC_IRQHandler(&hadc); } } diff --git a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.cpp b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.cpp index b0b43062..48fa866f 100644 --- a/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.cpp +++ b/src/current_sense/hardware_specific/stm32/stm32l4/stm32l4_hal.cpp @@ -6,7 +6,8 @@ #define SIMPLEFOC_STM32_DEBUG -ADC_HandleTypeDef hadc; +// pointer to the ADC handles used in the project +ADC_HandleTypeDef hadc[ADC_COUNT] = {0}; /** * Function initializing the ADC and the injected channels for the low-side current sensing @@ -22,9 +23,14 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ - hadc.Instance = _findBestADCForPins(3, cs_params->pins); + auto adc_instance = _findBestADCForPins(3, cs_params->pins, hadc); + int adc_num = _adcToIndex(adc_instance); + if (hadc[adc_num].Instance != NP) { + SIMPLEFOC_DEBUG("STM32-CS: ERR: ADC already in use: ADC", adc_num + 1); + return -1; + } - if(hadc.Instance == ADC1) { + if(adc_instance == ADC1) { #ifdef __HAL_RCC_ADC1_CLK_ENABLE __HAL_RCC_ADC1_CLK_ENABLE(); #endif @@ -33,7 +39,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive #endif } #ifdef ADC2 - else if (hadc.Instance == ADC2) { + else if (adc_instance == ADC2) { #ifdef __HAL_RCC_ADC2_CLK_ENABLE __HAL_RCC_ADC2_CLK_ENABLE(); #endif @@ -43,7 +49,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC3 - else if (hadc.Instance == ADC3) { + else if (adc_instance == ADC3) { #ifdef __HAL_RCC_ADC3_CLK_ENABLE __HAL_RCC_ADC3_CLK_ENABLE(); #endif @@ -56,7 +62,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC4 - else if (hadc.Instance == ADC4) { + else if (adc_instance == ADC4) { #ifdef __HAL_RCC_ADC4_CLK_ENABLE __HAL_RCC_ADC4_CLK_ENABLE(); #endif @@ -69,7 +75,7 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #endif #ifdef ADC5 - else if (hadc.Instance == ADC5) { + else if (adc_instance == ADC5) { #if defined(ADC345_COMMON) __HAL_RCC_ADC345_CLK_ENABLE(); #endif @@ -83,23 +89,24 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive } #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", _adcToIndex(&hadc)+1); -#endif - - hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; - hadc.Init.Resolution = ADC_RESOLUTION_12B; - hadc.Init.ScanConvMode = ADC_SCAN_ENABLE; - hadc.Init.ContinuousConvMode = DISABLE; - hadc.Init.LowPowerAutoWait = DISABLE; - hadc.Init.DiscontinuousConvMode = DISABLE; - hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; - hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now - hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; - hadc.Init.NbrOfConversion = 1; - hadc.Init.DMAContinuousRequests = DISABLE; - hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; - hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED; - if ( HAL_ADC_Init(&hadc) != HAL_OK){ + SIMPLEFOC_DEBUG("STM32-CS: Using ADC: ", adc_num+1); +#endif + + hadc[adc_num].Instance = adc_instance; + hadc[adc_num].Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; + hadc[adc_num].Init.Resolution = ADC_RESOLUTION_12B; + hadc[adc_num].Init.ScanConvMode = ADC_SCAN_ENABLE; + hadc[adc_num].Init.ContinuousConvMode = DISABLE; + hadc[adc_num].Init.LowPowerAutoWait = DISABLE; + hadc[adc_num].Init.DiscontinuousConvMode = DISABLE; + hadc[adc_num].Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc[adc_num].Init.ExternalTrigConv = ADC_SOFTWARE_START; // for now + hadc[adc_num].Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc[adc_num].Init.NbrOfConversion = 1; + hadc[adc_num].Init.DMAContinuousRequests = DISABLE; + hadc[adc_num].Init.EOCSelection = ADC_EOC_SINGLE_CONV; + hadc[adc_num].Init.Overrun = ADC_OVR_DATA_PRESERVED; + if ( HAL_ADC_Init(&hadc[adc_num]) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init ADC!"); #endif @@ -160,15 +167,15 @@ int _adc_init(Stm32CurrentSenseParams* cs_params, const STM32DriverParams* drive if (!_isset(cs_params->pins[i])) continue; sConfigInjected.InjectedRank = _getADCInjectedRank(channel_no++); - sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance); - if (HAL_ADCEx_InjectedConfigChannel(&hadc, &sConfigInjected) != HAL_OK){ + sConfigInjected.InjectedChannel = _getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance); + if (HAL_ADCEx_InjectedConfigChannel(&hadc[adc_num], &sConfigInjected) != HAL_OK){ #ifdef SIMPLEFOC_STM32_DEBUG - SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc.Instance)); + SIMPLEFOC_DEBUG("STM32-CS: ERR: cannot init injected channel: ", (int)_getADCChannel(analogInputToPinName(cs_params->pins[i]), hadc[adc_num].Instance)); #endif return -1; } } - cs_params->adc_handle = &hadc; + cs_params->adc_handle = &hadc[adc_num]; return 0; } @@ -207,26 +214,32 @@ int _adc_gpio_init(Stm32CurrentSenseParams* cs_params, const int pinA, const int extern "C" { void ADC1_2_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[0].Instance != NP) + HAL_ADC_IRQHandler(&hadc[0]); + if (hadc[1].Instance != NP) + HAL_ADC_IRQHandler(&hadc[1]); } #ifdef ADC3 void ADC3_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[2].Instance != NP) + HAL_ADC_IRQHandler(&hadc[2]); } #endif #ifdef ADC4 void ADC4_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[3].Instance != NP) + HAL_ADC_IRQHandler(&hadc[3]); } #endif #ifdef ADC5 void ADC5_IRQHandler(void) { - HAL_ADC_IRQHandler(&hadc); + if (hadc[4].Instance != NP) + HAL_ADC_IRQHandler(&hadc[4]); } #endif }