cancel
Showing results for 
Search instead for 
Did you mean: 

ADC cannot read multiple channels ..

Raider E
Associate III
Posted on December 16, 2016 at 00:08

The original post was too long to process during our migration. Please click on the attachment to read the original post.
9 REPLIES 9
Seb
ST Employee
Posted on December 16, 2016 at 01:00

How about using ADC Injected Channels? They have a Data Register per channel ==> no DMA needed ==> Simpler?

Raider E
Associate III
Posted on December 16, 2016 at 01:04

Ok now I diabled DMA and wrote the following :

HAL_ADC_Start(&hadc1);

HAL_ADC_PollForConversion(&hadc1,1000);

value[0]= HAL_ADC_GetValue(&hadc1);

value[1]= HAL_ADC_GetValue(&hadc1);

HAL_ADC_Stop(&hadc1);

sConfig.Channel = ADC_CHANNEL_2;

sConfig.Rank = 2;

sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

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

{

Error_Handler();

}

sConfig.Channel = ADC_CHANNEL_0;

sConfig.Rank = 1;

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

{

Error_Handler();

}

and it reads two channels. However, it reads OK for few seconds and then the the values swap for a second and then come back, so value[0] becomes value[1] and vice versa and only happes for a second then its fine. Further why it reads 

ADC_CHANNEL_2 in value[0], I though the one with the lower rank number will be read first, is that correct?

Posted on December 16, 2016 at 01:07

Hi  Seb,

thank you for your reply, i am still in my early stages learning and not sure how the injected channels mode work. any example code for the multi channels using an injected channel mode I can start with? many thanks

Posted on December 16, 2016 at 04:01

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6qr&d=%2Fa%2F0X0000000bwk%2FyASKeBOw_ZnyUKbhWthXE32VRcUnAfQI3KzzJqkZrUk&asPdf=false
Posted on December 16, 2016 at 05:53

Hi Seb,

thanks for that. I'll go through it and see. How about my code above with polling, it is working for me to read multi channels but not sure about processing time, is it going to be very slow?

Thank you

Esam

Posted on December 16, 2016 at 05:55

HAL_ADC_Start(&hadc1);

HAL_ADC_PollForConversion(&hadc1,1000);

value[0]= HAL_ADC_GetValue(&hadc1);

HAL_ADC_PollForConversion(&hadc1,1000);

value[1]= HAL_ADC_GetValue(&hadc1);

HAL_ADC_Stop(&hadc1);

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_DIV2;

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 = 2;

hadc1.Init.DMAContinuousRequests = ENABLE;

hadc1.Init.EOCSelection = ADC_EOC_SINGLE_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_2;

sConfig.Rank = 2;

sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

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

{

Error_Handler();

}

sConfig.Channel = ADC_CHANNEL_0;

sConfig.Rank = 1;

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

{

Error_Handler();

}

}
Posted on December 16, 2016 at 09:10

Your version looks like a 'one shot mode', controlled by SW.

It really depends on how often you need ADC data and if you'd like to react (interrupt) when reaching a certain value (analog watchdog).

The continuous mode on injected channel will automatically convert both channel in a cyclic fashion, and the SW can do something else.

The best example to illustrate this is to use DMA and a trigger from TIMER CC : You would then create a low frequency oscilloscope.

Do this also with a DAC and you'll get a waveform generator to feed the ADC. ADC sample at 1MHz range. A more challenge solution would be to inject an analog signal (ADC), run it through a digital filter (Kalman or pass band) and push it to the DAC or Matlab/Simulink....

Raider E
Associate III
Posted on December 19, 2016 at 01:29

Hi again,

I am trying to use DMA now as its more straightforward but still not working for me. Ain[0 below is only reading some weired voltage .17 instead of 1.3V and Ain[1] reads nothing stays 0.  can you please have a look and let me know what might have gone wrong:

#include 'stm32f7xx_hal.h'

#include 'global.h'

#define NO_OF_CHANNELS 2

#define NO_OF_ADCs 1

//Note that Interrupts for all peripherals are located in the xxx_msp file and xxx_it

void MX_ADC1_Init(void);

void MX_DMA_Init(void);

void readAins(void);

void MX_DMA_Init(void)

{

/* DMA controller clock 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);

}

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_DIV2;

hadc1.Init.Resolution = ADC_RESOLUTION_12B;

hadc1.Init.ScanConvMode = ENABLE;

hadc1.Init.ContinuousConvMode = DISABLE;

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 = 2;

hadc1.Init.DMAContinuousRequests = ENABLE;

hadc1.Init.EOCSelection = DISABLE;

HAL_ADC_Init(&hadc1);

// 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_2;

sConfig.Rank = 2;

sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;

HAL_ADC_ConfigChannel(&hadc1, &sConfig);

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

{

Error_Handler();

}

sConfig.Channel = ADC_CHANNEL_0;

sConfig.Rank = 1;

HAL_ADC_ConfigChannel(&hadc1, &sConfig);

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

{

Error_Handler();

}

// All Channels has to be preconfgured here as above

}

void readAins(void){

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&value2, 2);

Ain[0]=value2[0];

Ain[1]=value2[1];

}

msp file:

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

PA0/WKUP ------> ADC1_IN0

PA1 ------> ADC1_IN1

*/

GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;

GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

GPIO_InitStruct.Pull = GPIO_NOPULL;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* USER CODE BEGIN ADC1_MspInit 1 */

/* USER CODE END ADC1_MspInit 1 */

/* 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_WORD;

hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;

hdma_adc1.Init.Mode = DMA_CIRCULAR;

hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;

hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

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);

// if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)

// {

// Error_Handler();

// }

__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);

}

}

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 */

__HAL_RCC_ADC1_CLK_DISABLE();

/**ADC1 GPIO Configuration

PA0/WKUP ------> ADC1_IN0

PA1 ------> ADC1_IN1

*/

HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0|GPIO_PIN_1);

/* Peripheral DMA DeInit*/

HAL_DMA_DeInit(hadc->DMA_Handle);

// __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);

}

/* USER CODE BEGIN ADC1_MspDeInit 1 */

/* USER CODE END ADC1_MspDeInit 1 */

}

Posted on January 22, 2017 at 08:10

Hi, did you get it working ?