cancel
Showing results for 
Search instead for 
Did you mean: 

ADC samples get corrupted at end of sampling series

patrickbrataas9
Associate II
Posted on August 04, 2013 at 13:51

MCU: Cortex M3, STM32F103VC

I am using a DDS to generate a constant sinusoidal wave. I am sampling this wave and the last 160 samples are almost all garbage. No matter if I sample 7000 samples or 360, the last 160 is way off. I have ruled out that DDS is the problem by sampling the MCU 3V3 pin and it still gives error on the last 160 samples. I was wondering if anyone else have had similar problem or see any error in my code? (code shown below are a simplified/shortcut version of whatI am using, but is working and gives the same corrupted data) Here are some sample images:

http://imgur.com/CeMv0H4

http://imgur.com/kCOLbXG

http://imgur.com/8kiTWTD

EDITstart: I expanded the

ADCdata

array to be initialized as

ADCdata

[7200+160] instead of

ADCdata

[7200]when sampling 7200 and I did not get corrupted data. This might mean the the ADC is not the one corrupting the data but something else? Don't see what it can be though...

http://imgur.com/nDStvBD

EDITfinished. Here are relevant code:

void ADC_Initialization(void) 
{ 
GPIO_InitTypeDef GPIO_InitStructure; 
ADC_InitTypeDef ADC_InitStructure; 
//ADC clk = APB2 clk / 6 = 72MHz/6 = 12MHz. MAX 14MHz. 
RCC_ADCCLKConfig(RCC_PCLK2_Div6); 
RCC_APB2PeriphClockCmd( (RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC) , ENABLE); 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 
GPIO_Init(GPIOC, &GPIO_InitStructure); 
//DMA_ADC_Initialization(); 
//ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; 
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 
ADC_InitStructure.ADC_ScanConvMode = DISABLE; 
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 
//ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; 
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
ADC_InitStructure.ADC_NbrOfChannel = 1; 
ADC_Init(ADC1, &ADC_InitStructure); 
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_7Cycles5); 
//ADC_DMACmd(ADC1, ENABLE); 
//Enable timer 1 compare as external trigger 
//ADC_ExternalTrigConvCmd(ADC1, ENABLE); 
//Enable ADC1 
ADC_Cmd(ADC1, ENABLE); 
/* 
//Reset ADC1 calibration register 
ADC_ResetCalibration(ADC1); 
//Wait until ADC1 reset is done 
while(ADC_GetResetCalibrationStatus(ADC1) == SET); 
//Start ADC1 calibration 
ADC_StartCalibration(ADC1); 
//Wait until ADC1 calibration is done 
while(ADC_GetCalibrationStatus(ADC1) == SET); 
*/ 
//DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); 
} 
void TIMER1_Init(void) 
{ 
NVIC_InitTypeDef NVIC_InitStructure; 
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
//Enable Timer 2 clock 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); 
//Base 
TIM_TimeBaseStructure.TIM_Prescaler = 0; 
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
TIM_TimeBaseStructure.TIM_Period = 60167; 
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); 
TIM_ARRPreloadConfig(TIM1, ENABLE); 
//Register with Nested Vectored Interrupt Controller (NVIC). 
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; 
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0B; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0B; 
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
NVIC_Init(&NVIC_InitStructure); 
//Clear timer 
TIM_SetCounter(TIM1, 0); 
//Interrupt 
TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE); 
} 
void TIMER1_Enable(void) 
{ 
//Clear timer 
TIM_SetCounter(TIM1, 0); 
//Enable timer 
TIM_Cmd(TIM1, ENABLE); 
} 
void TIMER1_Disable(void) 
{ 
//Disable timer 
TIM_Cmd(TIM1, DISABLE); 
} 
void TIM1_CC_IRQHandler(void) 
{ 
uint16_t i; 
static uint16_t j = 0; 
LED(LED1, ON); 
ADC_SoftwareStartConvCmd(ADC1, ENABLE); 
while( !ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) ); 
ADCdata[j] = ADC_GetConversionValue(ADC1); 
j++; 
if(j == 7200) 
{ 
TIMER1_Disable(); 
printf(''_plotEnable\n''); 
for(i = 0; i < 7200; i++) 
{ 
printf(''%u, '', (uint16_t) (ADCdata[i] & 0x0FFF)); 
} 
printf(''\n''); 
} 
//Clear timer 1 compare interrupt 
TIM_ClearITPendingBit(TIM1, TIM_IT_CC1); 
} 
void main(void) 
{ 
TIMER1_Enable(); 
while(TRUE) 
{ 
} 
}

#adc-timer-cortexm3
2 REPLIES 2
Posted on August 04, 2013 at 17:52

Unfortunately this looks to be one of those incomplete examples. If you have stuff that doesn't work, don't selectively summarize/editoralize the code to the point where critical detail is lost.

I would probably have done different things in the interrupt, like clearing it on entry after confirming the source. I would have made sure to have bounds tested the index. Doing printf's there and waiting on EOC cause it the dwell in there too long. I don't think this causes the loss of samples. The NVIC priority parameters appear bogus, again not impacting things, but probably something to look harder at.

From the example it's not exactly clear, where and what size the buffer actually is.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
patrickbrataas9
Associate II
Posted on August 04, 2013 at 18:27

You are right, the size of the array is missing (but mentioned in the text), but that is the only thing that I can see. And what I meant about ''stripping'' the code is like you mentioned, I use printf in an interrupt routine, dont use DMA atm because the same corrupted data happend without DMA so it is just useless information, so I stripped it... The code is still fully runnable?