cancel
Showing results for 
Search instead for 
Did you mean: 

How to read several ADCs interfaces every n seconds per channel in STM32 MCU?

Marco S
Associate II
Posted on April 14, 2017 at 15:45

The original post was too long to process during our migration. Please click on the attachment to read the original post.
4 REPLIES 4
Jinhui Lin
Associate II
Posted on April 15, 2017 at 15:23

If you want to read multi-channel-adc, DMA Mode maybe the better way to do it, for example

PC1 ------> ADC1_IN11, 

PC4 ------> ADC1_IN14, 

PA2 ------> ADC1_IN2,  

PC5 ------> ADC1_IN15

 :

0690X00000606jbQAA.png0690X00000606mWQAQ.png

1. 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 memnory

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

}
Posted on April 15, 2017 at 17:25

Not a HAL guy, but pretty sure you'd need to increment the Rank number

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on April 17, 2017 at 12:50

 ,

 ,

The rank number appears as a fixed number in the HAL of the ADC:

♯ define ADC_RANK_CHANNEL_NUMBER , , , , , , , , , , , , , , , , (0x00001000U) , /*!<, Enable the rank of the selected channels. Number of ranks in the sequence is defined by number of channels enabled, rank of each channel is defined by channel number (channel 0 fixed on rank 0, channel 1 fixed on rank1, ...) */

It is not clear to me how does it work or how could I change it.

Posted on April 26, 2017 at 11:37

I think the MCU I'm using is more limited than yours. This is what I can configure in CubeMX:

0690X00000606q8QAA.png

I haven't find any way to configure different ranks for each ADC channel. What I have finally done is to enable the ADC interrupts and work in interrupt mode:

0690X00000606shQAA.png

It seems to work fine but I would like to know if there is any way to us the DMA as well.