cancel
Showing results for 
Search instead for 
Did you mean: 

Multichannel (scan), single conversion mode

Rogers.Gary
Senior II

I need to implement a single channel software triggered ADC scan in an interrupt callback paced at 10ms intervals, since the rate cannot be controlled in DMA.

I never had an issue doing this with CMSIS, yet, HAL seems to be, well, difficult is the nicest word I will use.

I am confident my code is set up correctly, because before the scheduler starts, I have a "while" test loop that run 10 times, and the values come out correctly. Yet, in the callback, it chokes to death and causes faults. Why, that's just like HAL.

Here is the init code for the ADC.

void MX_ADC1_Init(void)

{

 ADC_MultiModeTypeDef multimode = {0};

 ADC_ChannelConfTypeDef sConfig = {0};

 /** Common config

 */

 hadc1.Instance = ADC1;

 hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;

 hadc1.Init.Resolution = ADC_RESOLUTION_12B;

 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

 hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;

 hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

 hadc1.Init.LowPowerAutoWait = DISABLE;

 hadc1.Init.ContinuousConvMode = DISABLE;

 hadc1.Init.NbrOfConversion = 2;

 hadc1.Init.DiscontinuousConvMode = DISABLE;

 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

 hadc1.Init.DMAContinuousRequests = DISABLE;

 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;

 hadc1.Init.OversamplingMode = DISABLE;

 if (HAL_ADC_Init(&hadc1) != HAL_OK)

 {

   Error_Handler();

 }

 /** Configure the ADC multi-mode

 */

 multimode.Mode = ADC_MODE_INDEPENDENT;

 if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)

 {

   Error_Handler();

 }

 /** Configure Regular Channel

 */

 sConfig.Channel = ADC_CHANNEL_13;

 sConfig.Rank = ADC_REGULAR_RANK_1;

 sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5;

 sConfig.SingleDiff = ADC_SINGLE_ENDED;

 sConfig.OffsetNumber = ADC_OFFSET_NONE;

 sConfig.Offset = 0;

 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

 {

   Error_Handler();

 }

 /** Configure Regular Channel

 */

 sConfig.Channel = ADC_CHANNEL_14;

 sConfig.Rank = ADC_REGULAR_RANK_2;

 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

 {

   Error_Handler();

 }

}

Here's the code before launch:

MX_ADC1_Init();

HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED); 

And in the TIM2 callback @ 10ms intervals:

{

      HAL_ADC_Start(&hadc1);

       HAL_ADC_PollForConversion(&hadc1, 50);

       accumulator[TEMP] += HAL_ADC_GetValue(&hadc1);

       HAL_ADC_PollForConversion(&hadc1, 50);

       accumulator[VBAT] += HAL_ADC_GetValue(&hadc1);       

       HAL_ADC_Stop(&hadc1);       

//when count reaches 100, divide accumulator by count and get voltages/temps

}

It's BROKE as broke can be. I have been fighting with this thing for too many hours. Dear ST, HAL has not made things easier, at all.

Can anyone please provide a clue. Where could the problem be?

If I continue to have these problems, I will have the L4 processors removed from my boards and have F4's put in, and go back to CMSIS. Where things worked and I still had hair.

22 REPLIES 22
Rogers.Gary
Senior II

Yup. Familiar with how DMA works. I said: "...I see no hit in efficiency, that might not be in many cases though....". The point was NOT to use a timer, as it causes an interrupt which has to be serviced. If the DMA controller is freewheeling it uses no primary core ticks.

Rogers.Gary
Senior II

Agreed totally David. 8)

It is not necessary for the timer to generate interrupts. It can trigger ADC conversions [e.g., generate Trigger Output Events (TRGO)] all in hardware.