2017-04-06 03:22 AM
Hi
I am trying to use the ADC in the STM32L07 as a multichannel scan. I have set up Cube for 3 analogue channels, AN0, Temperature and VRef Int. I have set it up for single scan usign the HAL_ADC_Start_IT(&hadc); command. Within the interupt routine I am checking the ADC_FLAG_EOC for after each channel completed, and the ADC_FLAG_EOS for after the complete scan is completed. When the HAL_ADC_Start_IT is called, I see the first channel with ADC_FLAG_EOC, but straight away the ADC_FLAG_EOS is also called. I am new to the chip, and not sure what I am doing wrong, can anyone advice me? My code is below, and attached is snap shot of the cube setting
Many Thanks
Scott
unsigned ADC_Raw[3];
unsigned char ADC_index=0; #define AD_VCCINT 2 #define AD_TEMP 1void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{ if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC)) { ADC_Raw[ADC_index++]=HAL_ADC_GetValue(hadc); ADC_raw = HAL_ADC_GetValue(hadc); } if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS)) { <<gets called straight after first conversion... ADC_index=0; Vdd = 3000 * (*VREFINT_CAL_ADDR)/ADC_Raw[AD_VCCINT]; temperature=(((int32_t)ADC_Raw[AD_TEMP]*Vdd/3000)-(int32_t)*TEMP30_CAL_ADDR); temperature*=(int32_t)(130-30); temperature/=(int32_t)(*TEMP130_CAL_ADDR - *TEMP30_CAL_ADDR); temperature+=30; } }static void MX_ADC_Init(void)
{ADC_ChannelConfTypeDef sConfig;
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/ hadc.Instance = ADC1; hadc.Init.OversamplingMode = DISABLE; hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.ContinuousConvMode = DISABLE; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc.Init.DMAContinuousRequests = DISABLE; hadc.Init.EOCSelection = ADC_EOC_SINGLE_SEQ_CONV; hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED; hadc.Init.LowPowerAutoWait = DISABLE; hadc.Init.LowPowerFrequencyMode = DISABLE; hadc.Init.LowPowerAutoPowerOff = DISABLE; if (HAL_ADC_Init(&hadc) != HAL_OK) { Error_Handler(); }/**Configure for the selected ADC regular channel to be converted.
*/ sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) { Error_Handler(); }/**Configure for the selected ADC regular channel to be converted.
*/ sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) { Error_Handler(); }/**Configure for the selected ADC regular channel to be converted.
*/ sConfig.Channel = ADC_CHANNEL_VREFINT; if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK) { Error_Handler(); }}
Note: this post was migrated and contained many threaded conversations, some content may be missing.2017-04-06 11:11 AM
Its a strange one. I have also tried what you suggested, just set ADC_EOC_SINGLE_CONV and it just carried out one conversion. Also tried ranking 1,2,3. I only called HAL_ADC_Start_IT(&hadc) once. So looks like for some reason its not sampling the other 2 channels.
Scott
2017-04-06 12:17 PM
Does changing
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;to
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD | ADC_SCAN_ENABLE;fix it?
2017-04-07 07:12 AM
Hi
Anyone had the same issue? I have went through the example many times and still get the same result.
Regards
Scott
2017-04-07 11:18 AM
Hi Scott:
I was also doing development, actually following the same example you are, and had the same issue!
On the debugger, I was following your same steps. When you hit your first breakpoint, do you also get an OVR flag set on the ISR register? I noticed I was, which I believe it means that the ADC is going faster than the interrupt can handle it. Maybe the interrupt overhead of CubeMX's code?
Anyway, I changed the clock to 'Synchronous Clock Mode / 4' and tried it again. If I put the breakpoint on the 'if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOS))' code block I can get the values of the three channels. However a breakpoint on the other 'if' block will make the ADC overrun.
Let me know if this helps, I hope it does!
Thanks,
-Eduardo
2017-04-09 11:47 AM
Hi Eduardo
Thanks for your reply, and a great help, cheers.
What you said is exactly what i am seeing. I am new to the STM32 , so still learning .I would have never throught of that one,as I always assumed as I was using the debugger everything would stop between breakpoints and wouldnt get OVR set. I have set the same as you with the clock mode /4 . But also had to slow down the ADC sample rate or still wouldnt work. I thought this was the speed between the each sample period, and nothing to do with each channel.
I like the CubeMX, but maybe its becasue I am new to this , but does save a lot of time. I might try setting the ADC up without using the CubeMX to see if this works without changing these settings.
Thanks Again
Scott
2017-04-10 11:43 AM
Hi
devlin.scott
,Regarding
ADC_EOC_SINGLE_SEQ_CONV use, this is already answered by
Joly.Jeanne
inhttps://community.st.com/0D50X00009Xkf0fSAB
For your second point regarding
ADC_EOC_SINGLE_SEQ_CONV, it is a feature possible on HW side but, since a couple of years, we did not findany use case in SW in the HAL driver. We use eitherADC_EOC_SINGLE_CONV orADC_EOC_SEQ_CONV. With your post, as this variable is not use, we decided to delete this variable. It will be as well available in the nextCubeMX release.
Hope this helps you.
Imen
2017-04-13 12:15 PM
Hi Imen
Thanks for your replies. I have set the ADC to only convert 1 channel at a time, and call HAL_ADC_Start_IT(&hadc); to start the convertion. What I am seeing is that the
ADC_EOC_SINGLE_CONV
does get called after each channel ,and I call HAL_ADC_Start_IT(&hadc); to start the next channel. Then when all 3 have been converted, theADC_EOC_SEQ_CONV does get called. Mind, as I probably dont need it as after the each
ADC_EOC_SINGLE_CONV
I can work out when all convertions are comlpeted.Scott
2017-06-07 11:30 AM
Hi
devlin.scott
have made any progress on this it?I have tearing my hair out trying to get read multiple channels using interrupts.
Im getting the same behaviour that you got: EOC flag followed directly after EOS flag.
Thanks
Nathan
2017-06-08 12:09 PM
Hi Nathan,
I never really got around the issue, but I dont the following:
I have 2 a/d channels and started sampling within my main() appliction with a HAL_ADC_Start_IT(hadc); and set ADC_index=0. When I get a EOC, I simply call HAL_ADC_Start_IT() again until all channels are read.
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{ if (__HAL_ADC_GET_FLAG(hadc, ADC_IT_EOC)) //received EOC { ADC_Raw[ADC_index++]=HAL_ADC_GetValue(hadc); //store value and increase channel if(ADC_index<3) //while not all channels read, start another interupt HAL_ADC_Start_IT(hadc);}
if (__HAL_ADC_GET_FLAG(hadc, ADC_IT_EOS))
{ /....... } }Regards
Scott
2017-06-08 04:41 PM
Ooops, typo error. I meant to say,' I do the following'. Instead of starting the interupt and end on a ADC_IT_EOS, I simply keep starting an interupt within the ADC_IT_EOC until all the channels are sampled. It would be great if someone managed to get this working.
Scott