cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 ADC working well in DMA but giving wrong values in polling mode

panrod
Associate II
Posted on June 14, 2018 at 12:00

I am struggling to get the STM32 ADC in polling mode, but am able to get correct values in DMA mode. I am using STM32F427 ADC1 channel 12 in 12-bit mode.  Here is the relevant code:

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct;

RCC_ClkInitTypeDef RCC_ClkInitStruct;

RCC_PeriphCLKInitTypeDef periphClockConfig;

/**Configure the main internal regulator output voltage

*/

__HAL_RCC_PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

/**Initializes the CPU, AHB and APB busses clocks

*/

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

RCC_OscInitStruct.HSEState = RCC_HSE_ON;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

RCC_OscInitStruct.PLL.PLLM = 4;

RCC_OscInitStruct.PLL.PLLN = 168;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

RCC_OscInitStruct.PLL.PLLQ = 4;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

/**Initializes the CPU, AHB and APB busses clocks

*/

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

/**Configure the Systick interrupt time

*/

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

/**Configure the Systick

*/

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

/* SysTick_IRQn interrupt configuration */

HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

}

static void MX_DMA_Init(void)

{

/* DMA controller clock enable */

__DMA2_CLK_ENABLE();

hdma2.Instance = DMA2_Stream4;

hdma2.Init.Channel = DMA_CHANNEL_0;

hdma2.Init.Direction = DMA_PERIPH_TO_MEMORY;

hdma2.Init.PeriphInc = DMA_PINC_DISABLE;

hdma2.Init.MemInc = DMA_MINC_ENABLE;

hdma2.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;

hdma2.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;

hdma2.Init.Mode = DMA_CIRCULAR;

hdma2.Init.Priority = DMA_PRIORITY_HIGH;

hdma2.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

hdma2.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;

hdma2.Init.MemBurst = DMA_MBURST_SINGLE;

hdma2.Init.PeriphBurst = DMA_PBURST_SINGLE;

if (HAL_DMA_Init(&hdma2) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

__HAL_LINKDMA(&hadc1, DMA_Handle, hdma2);

/* DMA interrupt init */

/* DMA2_Channe4_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, 10, 0);

HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);

}

/* ADC1 init function */

static void MX_ADC1_Init(void)

{

ADC_ChannelConfTypeDef sConfig;

__ADC1_CLK_ENABLE();

/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)

*/

#ifdef ADC_DMA

hadc1.Instance = ADC1;

hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;//ADC_CLOCK_SYNC_PCLK_DIV4; //Prescalar on 84 MHz

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

hadc1.Init.DMAContinuousRequests = ENABLE;//DISABLE;

hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

#else

hadc1.Instance = ADC1;

hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; //Prescalar on 84 MHz

hadc1.Init.Resolution = ADC_RESOLUTION_12B;

hadc1.Init.ScanConvMode = DISABLE;

hadc1.Init.ContinuousConvMode = ENABLE; //DISABLE;

hadc1.Init.DiscontinuousConvMode = DISABLE;

hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;

hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc1.Init.NbrOfConversion = 1;

hadc1.Init.DMAContinuousRequests = DISABLE;

hadc1.Init.EOCSelection = DISABLE;

#endif

if (HAL_ADC_Init(&hadc1) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.

*/

sConfig.Channel = ADC_CHANNEL_12;

sConfig.Rank = 1;

sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;//ADC_SAMPLETIME_3CYCLES;

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

{

_Error_Handler(__FILE__, __LINE__);

}

}

For using ADC counts in polling mode, in a 100 ms timer interrupt, I am doing this:

#ifndef ADC_DMA

if (HAL_ADC_PollForConversion(&hadc1, 1000) != HAL_OK)

{

errorCounter++;

}

/* Check if the continuous conversion of regular channel is finished */

if ((HAL_ADC_GetState(&hadc1) & HAL_ADC_STATE_EOC_REG) == HAL_ADC_STATE_EOC_REG)

{

gTemperatureValues = HAL_ADC_GetValue(&hadc1);

}

#endif

When I define the macro ADC_DMA and use the DMA and ADC interrupt callback functions, it works perfectly well and the array of 12-bit ADC counts is as expected.

However, due to some constraints, I want to use periodic polling instead of DMA/interrupt.

When I try to use the ADC in polling mode as above, the conversion works well, but every time, I am getting a random and incorrect 8-bit value in the ADC DR register in spite of configuring it for 12-bit mode.

Please suggest. Thanks in advance.

0 REPLIES 0