2018-06-14 03:00 AM
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); } #endifWhen 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.