Skip to main content
Marco S
Associate III
April 14, 2017
Question

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

  • April 14, 2017
  • 2 replies
  • 2090 views
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.
    This topic has been closed for replies.

    2 replies

    Jinhui Lin
    Associate
    April 15, 2017
    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();

    }
    Marco S
    Marco SAuthor
    Associate III
    April 26, 2017
    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.

    Tesla DeLorean
    Guru
    April 15, 2017
    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 VenmoUp vote any posts that you find helpful, it shows what's working..
    Marco S
    Marco SAuthor
    Associate III
    April 17, 2017
    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.