2020-10-07 01:07 AM
I get 12bit ADC data from DMA multi channel.
and when I get it , I use this formula to get ADC measure.
adc input (0-4095) * 3300 / 4095
but This result usually have different from real measurement, about 100-200mV.
In that case, Is there better way to correct data by other methode ?
here is my configuration codes.
I set adcBuffer[4] for get ADC-DMA data.
When I init like that, I use HAL_ADC_ConvCpltCallback for receiving .
--------------------------------------------------------------------------------------------------------------------------
static DMA_HandleTypeDef DmaHandle;
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO clock ****************************************/
__HAL_RCC_GPIOA_CLK_ENABLE();
/* ADC1 Periph clock enable */
//ADCx_CLK_ENABLE();
/* Enable DMA1 clock */
__HAL_RCC_DMA1_CLK_ENABLE();
/*********************** Configure DMA parameters ***************************/
DmaHandle.Instance = DMA1_Channel1;
DmaHandle.Init.Direction = DMA_PERIPH_TO_MEMORY;
DmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
DmaHandle.Init.MemInc = DMA_MINC_ENABLE;
DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
DmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
DmaHandle.Init.Mode = DMA_CIRCULAR;
DmaHandle.Init.Priority = DMA_PRIORITY_MEDIUM;
DmaHandle.Init.Request = DMA_REQUEST_0;
/* Deinitialize & Initialize the DMA for new transfer */
HAL_DMA_DeInit(&DmaHandle);
HAL_DMA_Init(&DmaHandle);
/* Associate the DMA handle */
__HAL_LINKDMA(&hadc, DMA_Handle, DmaHandle);
/* NVIC configuration for DMA Input data interrupt */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
/* USER CODE BEGIN ADC_Init 0 */
/* USER CODE END ADC_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC_Init 1 */
/* USER CODE END ADC_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; //need to be 2?
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
//ADC_SAMPLETIME_79CYCLES_5; //7 _ 5 ?
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = ENABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DMAContinuousRequests = ENABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/* ### - 2 - Start calibration ############################################ */
if (HAL_ADCEx_Calibration_Start(&hadc , ADC_SINGLE_ENDED) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_1 | ADC_CHANNEL_3 | ADC_CHANNEL_8 | ADC_CHANNEL_TEMPSENSOR ; //tempsensor == ch 18 !
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER; //ranked by channel number
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC_Init 2 */
/* if (HAL_ADC_Start(&hadc ) != HAL_OK)
{
Error_Handler();
}
*/
if (HAL_ADC_Start_DMA(&hadc,
(uint32_t*) &adcBuffer,
4 //SIZE OF ADC MULTI CHANNEL
) != HAL_OK)
{
Error_Handler();
}
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); //DMA-ADC begins
Thanks for read.
2020-10-07 08:17 AM
There is an app note "How to get the best ADC accuracy in STM32 microcontrollers" with some general tips and remarks.