Is a safe way to convert others ADC channels using the same interrupt mechanism employed by a FOC 4.0 library?
Hi,
I'm here to ask if someone knows a safe way to convert other analog sources using the ADC macrocells
of a STM32F407ZE MCU used to spin a BLDC motor by means of a FOC 4.0 library.
I mean, is there a way to correctly hook my code to the ADC IRQ Handler employed by FOC to manage
its tasks? Unfortunately we haven't the code of FOC library, so I do not know how to accomplish this task.
I have to convert the analog signals coming from 4 NTC resistors, and other two signals. They are attached
to ADC channels belonging to ADC2 and ADC3 (someone told me that FOC uses ADC module 1 and ADC
module 2).
At the moment the only way to accomplish this task is to run this code (after FOC initialization):
/* Enable ADC2 and GPIO clocks ****************************************/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
/* Configure ADC2 Channel3 pin as analog input ******************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ADC Common Init **********************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC2 Init ****************************************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC2, &ADC_InitStructure);
/* ADC2 regular channel 3 configuration **************************************/
ADC_RegularChannelConfig(ADC2, ADC_Channel_3, 1, ADC_SampleTime_56Cycles);
/* Enable ADC2 */
ADC_Cmd(ADC2, ENABLE);
/* Enable ADC3 and GPIO clocks ****************************************/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
/* Configure pins as analog input ******************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOF, &GPIO_InitStructure);
/* ADC Common Init **********************************************************/
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC3 Init ****************************************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_CC1;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC3, &ADC_InitStructure);
/* ADC3 regular channels configuration **************************************/
ADC_RegularChannelConfig(ADC3, ADC_Channel_8, 1, ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC3, ADC_Channel_9, 1, ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC3, ADC_Channel_14, 1, ADC_SampleTime_56Cycles);
ADC_RegularChannelConfig(ADC3, ADC_Channel_15, 1, ADC_SampleTime_56Cycles);
/* Enable ADC3 */
ADC_Cmd(ADC3, ENABLE);
Basically I program every ADC channel in the same way: ADC1,2,3 modules in Indipendent Mode, every ADC module to act for a singular conversion (no scan mode).
Then in the main loop I execute the following code:
uint16_t usCurrent1;
uint16_t usCurrent2;
uint16_t usNTC1;
uint16_t usNTC2;
uint16_t usNTC3;
/* Single conversion */
ADC_RegularChannelConfig(ADC2, ADC_Channel_3, 1, ADC_SampleTime_56Cycles);
ADC_SoftwareStartConv(ADC2);
while (ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC) == RESET) {}
usCurrent1 = ADC_GetConversionValue(ADC2) >> 4;
ADC_RegularChannelConfig(ADC3, ADC_Channel_8, 1, ADC_SampleTime_56Cycles);
ADC_SoftwareStartConv(ADC3);
while (ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET) {}
usCurrent2 = ADC_GetConversionValue(ADC3) >> 4;
ADC_RegularChannelConfig(ADC3, ADC_Channel_9, 1, ADC_SampleTime_56Cycles);
ADC_SoftwareStartConv(ADC3);
while (ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET) {}
usNTC1 = ADC_GetConversionValue(ADC3) >> 4;
ADC_RegularChannelConfig(ADC3, ADC_Channel_14, 1, ADC_SampleTime_56Cycles);
ADC_SoftwareStartConv(ADC3);
while (ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET) {}
usNTC2 = ADC_GetConversionValue(ADC3) >> 4;
ADC_RegularChannelConfig(ADC3, ADC_Channel_15, 1, ADC_SampleTime_56Cycles);
ADC_SoftwareStartConv(ADC3);
while (ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET) {}
usNTC3 = ADC_GetConversionValue(ADC3) >> 4;Practically, not knowing how to hook-up to the ADC interrupt handler code implemented in the FOC 4.0, I used
a "polling" approach configuring the ADC macrocell to make a singular conversion of the selected channel and
waiting for the End Of Conversion of that channel.
What I can see is that usCurrent1, usCurrent3, usNTC1, usNTC3 and usNTC3 takes three kinds of strange values
(near 0, near 511 and near 1023). I think this behavior is due to the fact that the FOC and my pieces of code interact
in the wrong way.
Someone can tell me if I made the wrong approach and/or if there is another way to solve this problem?
Thank in advance everyone can help me..