cancel
Showing results for 
Search instead for 
Did you mean: 

how to read multi channel ADC ?

kalpeshpatil102
Associate III
Posted on December 30, 2016 at 13:53

hi , i am using STM32fo with cube mx and keil mdk5. in my project i have to read muti channel ADC value . For this when i used DMA  , DMA has its interrupt and in my project i already used timer interrupt so these two get conflict. i didn't used DMA function.

when i used below function  in my project than the channel1 and channel 2 value swapping with each other . i didn't get channel1 value to channel1 and 

channel2 value to channel2.

while(1){ HAL_ADC_Start(&hadc);

while(HAL_ADC_PollForConversion(&hadc,0) != HAL_OK);

channel_1 = HAL_ADC_GetValue(&hadc); while(HAL_ADC_PollForConversion(&hadc,0) != HAL_OK);

channel_2= HAL_ADC_GetValue(&hadc); HAL_ADC_Stop(&hadc); }

please help me how to read correct value of each channel .

sorry for poor English 

thank you

3 REPLIES 3
Seb
ST Employee
Posted on December 30, 2016 at 14:15

It looks like there is a missing function call to actually select which channel to convert. Here it looks like the same channel is converted twice. Look at the header file of the HAL for ADC to find out what function is missing.

kalpeshpatil102
Associate III

Posted on January 02, 2017 at 04:44

marsanne.sebastien

‌ thank you and sorry for late reply , i am configuring channel using HAL function like this

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
/* ADC init function */
 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.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
 hadc.Init.Resolution = ADC_RESOLUTION_12B;
 hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
 hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
 hadc.Init.LowPowerAutoWait = DISABLE;
 hadc.Init.LowPowerAutoPowerOff = DISABLE;
 hadc.Init.ContinuousConvMode = ENABLE;
 hadc.Init.DiscontinuousConvMode = DISABLE;
 hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc.Init.DMAContinuousRequests = ENABLE;
 hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
 if (HAL_ADC_Init(&hadc) != HAL_OK)
 {
 Error_Handler();
 } 
/**Configure for the selected ADC regular channel to be converted. 
 */
 sConfig.Channel = ADC_CHANNEL_0;//////////////////
 channel 0
 sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
 sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
 if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
 {
 Error_Handler();
 } 
/**Configure for the selected ADC regular channel to be converted. 
 */
 sConfig.Channel = ADC_CHANNEL_1;
 channel 1
 if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
 {
 Error_Handler();
 } 
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
the function works when only this test code is run .
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
while(1){
 HAL_ADC_Start(&hadc);
while(HAL_ADC_PollForConversion(&hadc,0) != HAL_OK);
channel_1 = HAL_ADC_GetValue(&hadc);
 while(HAL_ADC_PollForConversion(&hadc,0) != HAL_OK);
channel_2= HAL_ADC_GetValue(&hadc); HAL_ADC_Stop(&hadc);
 }
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

when put this function in my main code than is swapping the values of channel. And in main code i used timer interrupt with function of output compere no output. This timer function is used to generate 6 different case. .In my main code i want read ADC value at specific timer interval . So when values of channel are swapping this affect on another function . So how can read channel values without swapping ?

thank you

Jinhui Lin
Associate II

Posted on April 15, 2017 at 12:54

Use DMA Mode to read multi-channel-adc looks fine,

for example

PC1 ------> ADC1_IN11, 

PC4 ------> ADC1_IN14, 

PA2 ------> ADC1_IN2, 

PC5 ------> ADC1_IN15:

0690X00000606lrQAA.png0690X00000606mZQAQ.png1. ADC Initial : for channel with 4 different rank

/* ADC1 init function */
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
 */
 hadc1.Instance = ADC1;
 hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
 hadc1.Init.Resolution = ADC_RESOLUTION_12B;
 hadc1.Init.ScanConvMode = ENABLE;
 hadc1.Init.ContinuousConvMode = ENABLE;
 hadc1.Init.DiscontinuousConvMode = DISABLE;
 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 hadc1.Init.NbrOfConversion = 4;
 hadc1.Init.DMAContinuousRequests = ENABLE;
 hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
 if (HAL_ADC_Init(&hadc1) != HAL_OK)
 {
 Error_Handler();
 }
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
 */
 sConfig.Channel = ADC_CHANNEL_11;
 sConfig.Rank = 1;
 sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
 */
 sConfig.Channel = ADC_CHANNEL_2;
 sConfig.Rank = 2;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
 */
 sConfig.Channel = ADC_CHANNEL_14;
 sConfig.Rank = 3;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
 */
 sConfig.Channel = ADC_CHANNEL_15;
 sConfig.Rank = 4;
 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
 {
 Error_Handler();
 }
}

2. DMA Initial : DMA NVIC

/** 
 * Enable DMA controller clock
 */
static void MX_DMA_Init(void) 
{
 /* DMA controller clock enable */
 __HAL_RCC_DMA1_CLK_ENABLE();
 __HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream0_IRQn interrupt configuration */
 HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}

3. MSP initial : adc' GPIO

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct;
 if(hadc->Instance==ADC1)
 {
 /* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
 /* Peripheral clock enable */
 __HAL_RCC_ADC1_CLK_ENABLE();
 /**ADC1 GPIO Configuration 
 PC1 ------> ADC1_IN11
 PC4 ------> ADC1_IN14
 PA2 ------> ADC1_IN2
 PC5 ------> ADC1_IN15 
 */
 GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Peripheral DMA init*/
 hdma_adc1.Instance = DMA2_Stream0;
 hdma_adc1.Init.Channel = DMA_CHANNEL_0;
 hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
 hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
 hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
 hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
 hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
 hdma_adc1.Init.Mode = DMA_NORMAL;
 hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
 hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
 if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
 {
 Error_Handler();
 }
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
 }
}

4. Read Multi-ADC-Channel to memory

static uint16_t adc_buffer[4];
// 
hadc1.Init.NbrOfConversion == 4
if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&adc_buffer, hadc1.Init.NbrOfConversion) != HAL_OK);
 HAL_Delay(500);
HAL_ADC_Stop_DMA(&hadc1);
and add what you want in completed callback function:
/**
 * @brief Conversion complete callback in non blocking mode
 * @param AdcHandle : AdcHandle handle
 * @note This example shows a simple way to report end of conversion, and
 * you can add your own implementation.
 * @retval None
 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
 // TODO
 __NOP();
}