cancel
Showing results for 
Search instead for 
Did you mean: 

How to define the data conversion order in multichannel ADC

rwmao
Senior
Posted on May 13, 2016 at 21:49

Hi

I am using stm32f4 chip to do multichannel ADC conversion. Very hard to figure out the ordr of the channel scanning. What do you think which channel was scanned first in the following codes? Very surprised that Ch4 was scanned first. I can't figure out why.

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
*/
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; //each conversion takes 3+15=18cycles. 18/12MHz=1.5us. 
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
*/
sConfig.Channel = ADC_CHANNEL_4;//PA4
sConfig.Rank = 2;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);

#no-hablo-hal
8 REPLIES 8
Posted on May 13, 2016 at 21:51

If it's not following the Rank#, then something else is wrong..

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
rwmao
Senior
Posted on May 13, 2016 at 22:05 Here is the code I used. This is the code I used to start conversion:

if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&uhADCxConvertedValue, 16) != HAL_OK)
{
//16points for 2channels. So each channel has 8 points
/* Start Conversation Error */
Error_Handler(''Error on start ADC''); 
}

in callback function, I do average of the data array.

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
sum1=0;
sum2=0;
count++;
for(int i=0;i<
8
;i++)
{
sum1+=uhADCxConvertedValue[i*2];
sum2+=uhADCxConvertedValue[i*2+1];
}
ADC_CurrentAverage=(uint16_t)((sum1>>3)*1.0/40*3300);
ADC_VoltageAverage=(uint16_t)((sum2>>3)*1.0/40*3300);
sum1=0;//no use
}

In the above code, the value of sum1 is found to be ch4(the second channel defined in the case). The definition of the codes are:

/* ADC1 init function */
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
*/
/* PCLK2 is the APB2 clock */
/* ADCCLK = PCLK2/8 = 96/12 = 12MHz*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV8; //clock setting. clock applied is 96MHz, /8=12MHz
hadc1.Init.Resolution = ADC_RESOLUTION12b;
hadc1.Init.ScanConvMode = ENABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc1);
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
*/
sConfig.Channel = ADC_CHANNEL_3;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; //each conversion takes 3+15=18cycles. 18/12MHz=1.5us. 
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
*/
sConfig.Channel = ADC_CHANNEL_4;//PA4
sConfig.Rank = 2;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}
/** 
* Enable DMA controller clock
*/
void MX_DMA_Init(void) 
{
/* DMA controller clock enable */
__DMA2_CLK_ENABLE();
/* DMA interrupt init */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}

function defined in hal_map.c

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 */
__ADC1_CLK_ENABLE();
/**ADC1 GPIO Configuration 
PA3 ------> ADC1_IN3
PA4 ------> ADC1_IN4 
*/
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4;
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_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_adc1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
hdma_adc1.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_adc1.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_adc1);
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspDeInit 0 */
/* USER CODE END ADC1_MspDeInit 0 */
/* Peripheral clock disable */
__ADC1_CLK_DISABLE();
/**ADC1 GPIO Configuration 
PA3 ------> ADC1_IN3
PA4 ------> ADC1_IN4 
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3|GPIO_PIN_4);
/* Peripheral DMA DeInit*/
HAL_DMA_DeInit(hadc->DMA_Handle);
}
/* USER CODE BEGIN ADC1_MspDeInit 1 */
/* USER CODE END ADC1_MspDeInit 1 */
}

rwmao
Senior
Posted on May 13, 2016 at 22:38

clivel,

you are right. it depends on the order of rank#.

Something is wrong with the code. 

I connected one of the channels to ground to check the order. The order is right. But the measured value is totally wrong, very big difference.

The weird thing is short of one channel would change another channel, significantly. 

Would you please help check the setting? anything wrong?

Thanks

rwmao
Senior
Posted on May 13, 2016 at 23:48

there is very big difference between the measured value and actural value.

I am testing the chip with DC source. I use multimeter to measure it, 1.995v. valued measured by the chip is 2.4v.

what is wrong?

Posted on May 14, 2016 at 00:27

I'll observe that the STM32F4-DISCO runs at 3.0V not 3.3V, you might want to double check what VREF is.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
rwmao
Senior
Posted on May 14, 2016 at 00:59

here is the problem.

I use stm32F411RET6 chip

first I measured the VREF+ on the board to be 2.5v. So I revised it to be 2.5v. Then I use the revised fomula for following testing.

1. only open single channel (ch4), the measured value with multimeter is 1.93(half of battery voltage).. with the calculation it is 1.88v. Maybe still acceptable.

2. Open two channels, ch4 and ch3. Ch3 actually is floating.

Then reading at ch4 is changed to 1.78v

Then I connect ch3 to ground, Read at ch4 is 1.46v.

?

Posted on May 14, 2016 at 18:15

The sampling circuit is capacitive in nature, so a floating input is going to neither charge or discharge the state from the previous channel.

Enough current must flow within the sampling window for the level to attain that of the input.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
rwmao
Senior
Posted on May 18, 2016 at 18:45

The channels do have a little bit interference, maybe as matter of input impedance.Here is the testing procedure.

1. set the program freuquently scanning two chs.

2.connect ch4 to voltage dividor, 100k+100k, meaning half of vdd.

3. connect ch1 to ground,read the number. Then reconnect it to vdd.

The reading of ch4 is changed. Note connection of ch4 has never been changed.

As the order of channels, clivel has cleared, depending on the rank#.

If the chs are connected to a solid source(not impedance dependent), the reading is OK.

Thanks Clivel.