cancel
Showing results for 
Search instead for 
Did you mean: 

Unexpected readings (2X or 0.5X) using ADC on STM32F0

osmaneralp
Associate II
Posted on November 10, 2014 at 20:07

I'm using the ADC on a STM32F072RBT6 to read a constant voltage that is derived from my supply voltage. Sometimes, I get a reading that is twice the expected value, and sometimes I get a reading that is half the expected value. The following data shows this problem:

... t 70210 v 46 ref 1228 t 70220 v 47 ref 1228 t 70230 v 89 ref 1229 <-- unexpected reading (2x) t 70240 v 45 ref 1228 t 70250 v 47 ref 1228 t 70260 v 49 ref 1228 t 70270 v 45 ref 1229 t 70280 v 49 ref 1229 t 70290 v 41 ref 1228 t 70300 v 48 ref 1228 t 70310 v 24 ref 1229<-- unexpected reading (0.5x) t 70310 v 47 ref 1228 t 70320 v 48 ref 1229 t 70330 v 48 ref 1228 t 70340 v 47 ref 1228

...

The expected value of v is about Does any know of anything related to the STM32F0 that might cause this problem? It seems like the SAR sometimes is off by one comparison. But the ref voltage doesn't show the problem. My ADC init code is shown below. TIA, Osman

/******************************************************************************/
void RCC_Configuration(void)
{
/* GPIOC clock enable */
//RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
/* ADC1 Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* DMA1 clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);
//RCC_ADCCLKConfig(RCC_ADCCLK_PCLK_Div4);
//RCC_ADCCLKConfig(RCC_ADCCLK_HSI14);
}
/******************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
/* ADC Channel 10 -> PC0 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
/******************************************************************************/
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* DMA1 Channel1 Config */
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADCData;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 2;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* DMA1 Channel1 enable */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* ADC DMA request in circular mode */
ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);
/* Enable ADC_DMA */
ADC_DMACmd(ADC1, ENABLE);
}
/******************************************************************************/
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
uint32_t calibrationFactor;
/* Initialize ADC structure */
ADC_StructInit(&ADC_InitStructure);
/* ADC1 Init */
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel 10 configuration */
ADC_ChannelConfig(ADC1, ADC_Channel_10, ADC_SampleTime_55_5Cycles); // PC0
/* Convert the ADC1 Vref with 5 Cycles as sampling time */
ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint , ADC_SampleTime_55_5Cycles);
ADC_VrefintCmd(ENABLE);
/* ADC1 Calibration */
calibrationFactor = ADC_GetCalibrationFactor(ADC1);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Wait the ADCEN falg */
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));
/* ADC1 regular Software Start Conv */
ADC_StartOfConversion(ADC1);
}
/******************************************************************************/
void initADC(void)
{
int i;
char obuf[OBUF_SIZE];
uint16_t mSense, ref;
/* ADC1 DeInit */
ADC_DeInit(ADC1);
RCC_Configuration();
GPIO_Configuration();
DMA_Configuration();
ADC_Configuration();
i = 0;
while(1) {
waitForTick();
mSense = (uint32_t)((ADCData[0]* 3300) / 0xFFF);
ref = (uint32_t)((ADCData[1]* 3300) / 0xFFF);
if (i++ == 0) {
snprintf(obuf,OBUF_SIZE,''t %ld v %ld ref %ld\n\r'', timer_g, mSense, ref);
writeUSART(USART1,obuf);
}
i %= 10;
}
}

#adc #stm32f0
1 REPLY 1
Posted on November 10, 2014 at 20:56

I'd probably make the buffer a bit bigger so the DMA didn't walk over the values I was working with. And I'd probably do the casting more appropriately.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..