Skip to main content
shami
Associate
April 1, 2019
Solved

Multichannel ADC DMA solution NOT working on stm32l4xx specifically ST32L496

  • April 1, 2019
  • 1 reply
  • 744 views

I am aware of the TIMER4 ADC_EXTERNALTRIG_T4_TRGO definition bug and have modified the file accordinginly . I have had this code working in single channel mode ( non DMA) but cannot get it working in multichannel DMA mode .

ADC_INIT()
{
 hadc3.Instance = ADC3;
 
 HAL_ADC_DeInit(&hadc3);
 
 hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
 hadc3.Init.Resolution = ADC_RESOLUTION_12B;
 hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;
 hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
 hadc3.Init.LowPowerAutoWait = DISABLE;
 hadc3.Init.ContinuousConvMode = DISABLE;
 hadc3.Init.NbrOfConversion = 4;
 hadc3.Init.DiscontinuousConvMode = DISABLE;
 hadc3.Init.NbrOfDiscConversion = 1;
 hadc3.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T4_TRGO;
 hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
 hadc3.Init.DMAContinuousRequests = DISABLE;
 hadc3.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
 hadc3.Init.OversamplingMode = DISABLE;
 if (HAL_ADC_Init(&hadc3) != HAL_OK) {
 _Error_Handler(__FILE__, __LINE__);
 }
 
 
 /**Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_1;
 sConfig.Rank = ADC_REGULAR_RANK_1;
 sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
 sConfig.SingleDiff = ADC_SINGLE_ENDED;
 sConfig.OffsetNumber = ADC_OFFSET_NONE;
 sConfig.Offset = 0;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) {
 _Error_Handler(__FILE__, __LINE__);
 }
 /**Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_6;
 sConfig.Rank = ADC_REGULAR_RANK_2;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) {
 _Error_Handler(__FILE__, __LINE__);
 }
 /**Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_8;
 sConfig.Rank = ADC_REGULAR_RANK_3;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) {
 _Error_Handler(__FILE__, __LINE__);
 }
 /**Configure Regular Channel
 */
 sConfig.Channel = ADC_CHANNEL_10;
 sConfig.Rank = ADC_REGULAR_RANK_4;
 if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK) {
 _Error_Handler(__FILE__, __LINE__);
 }
}
 
In hal_msp.cpp
 
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc) {
 
 GPIO_InitTypeDef GPIO_InitStruct = { 0 };
 
 /* Peripheral clock enable */
 HAL_RCC_ADC_CLK_ENABLED++;
 if (HAL_RCC_ADC_CLK_ENABLED == 1) {
 __HAL_RCC_ADC_CLK_ENABLE()
 ;
 }
 
 __HAL_RCC_GPIOC_CLK_ENABLE()
 ;
 __HAL_RCC_GPIOF_CLK_ENABLE()
 ;
 
 /* Enable clock of DMA associated to the peripheral */
 __HAL_RCC_DMA1_CLK_ENABLE()
 ;
 
 /**ADC3 GPIO Configuration
 PF3 ------> ADC3_IN6
 PF5 ------> ADC3_IN8
 PF7 ------> ADC3_IN10
 PC0 ------> ADC3_IN1
 */
 GPIO_InitStruct.Pin = Reference_voltage_for_A_Pin | Spare_temp_sensor_channel_Pin
 | Temperature_Sensor_on_Heat_sink_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = Reference_voltage_for_B_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG_ADC_CONTROL;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(Reference_voltage_for_B_GPIO_Port, &GPIO_InitStruct);
 
 /* ADC3 DMA Init */
 /* ADC3 Init */
 hdma_adc3.Instance = DMA1_Channel3;
 hdma_adc3.Init.Request = DMA_REQUEST_0;
 hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY;
 hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE;
 hdma_adc3.Init.MemInc = DMA_MINC_ENABLE;
 hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
 hdma_adc3.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;
 hdma_adc3.Init.Mode = DMA_CIRCULAR;
 hdma_adc3.Init.Priority = DMA_PRIORITY_HIGH;
 HAL_DMA_DeInit(&hdma_adc3);
 HAL_DMA_Init(&hdma_adc3);
 __HAL_LINKDMA(hadc, DMA_Handle, hdma_adc3);
 
 
}
 
Time init code not inserted . I do know the timer is running correctly 
 
Then To start the process
 MX_TIM_Init();
 ADC_INIT();
 HAL_TIM_Base_Start(&htim4);
 
 HAL_ADC_Start_DMA(&hadc3, (uint32_t *) aADCxConvertedValues, ADCCONVERTEDVALUES_BUFFER_SIZE);

This topic has been closed for replies.
Best answer by shami

Found my own mistake.  

In the process of testing other modes I have copied and pasted

hdma_adc3.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;

It should be

hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

1 reply

shami
shamiAuthorBest answer
Associate
April 2, 2019

Found my own mistake.  

In the process of testing other modes I have copied and pasted

hdma_adc3.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;

It should be

hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;