ADC artifacts in conti-mode STM32L100RC
Dear Community,
I’ve investigated the ADC of the STM32L100RC (DISCO-Board) in continuous and in the triggered mode.In continuous mode I was able to reach a sample frequency of ~300 kHz which I investigated experimentally by connecting the ADC input with an RF Generator and monitoring 100 bytes of sampled data via UART as a graph on my PC (some kind of oscilloscope) . I noticed artifacts while sampling in the continuous mode which I didn’t observed in the triggered mode. I would be very happy if someone could either found a mistake in my code or maybe confirm that that the STM32L100RC ADC produces artifacts if operated in continuous mode.
Here is some code which I combined from examples given in the SPL.
uint16_t ADCBuffer[200];
void
Timer2enable() {
//NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//Timer
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 0x01;
TIM_TimeBaseStructure.TIM_Prescaler = 0x0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
//TIM_TRGOSource_Update); // Copied from ST Form ''CLIVE1''
TIM_Cmd(TIM2, ENABLE);
//TIM_IT_Update Event
//TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //just for checking the timer is working as expected
};
void
ADC_IN18_DMA_INIT() {
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//DMA Interupt
// Enable DMA1 clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//DMA1 channel1 configuration
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADCBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize =
sizeof
(ADCBuffer);
//buffersize
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//Memory will be incrementet-> yes
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
//DMA_Mode_Normal; //
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
// Enable DMA1 channel6 IRQ Channel
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//DMA_IT_TC: Transfer complete interrupt mask
//DMA_IT_HT: Half transfer interrupt mask
//DMA_IT_TE: Transfer error interrupt mask
DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
// Configure PB.12 (ADC Channel18) in analog mode
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
//PB12 --> ADC_IN18
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//GPIOSpeed ??
// Enable ADC1 clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
// ADC1 configuration
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
//enable for conti - mode
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
//enable for conti - mode
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
//ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
//Trigger
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_18, 1, ADC_SampleTime_4Cycles);
// Enable the request after last transfer for DMA Circular mode
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
// Enable ADC1 DMA
ADC_DMACmd(ADC1, ENABLE);
// Enable ADC1
ADC_Cmd(ADC1, ENABLE);
// Wait until the ADC1 is ready
while
(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET) {}
// Start ADC1 Conversion
ADC_SoftwareStartConv(ADC1);
}
void
DMA1_Channel1_IRQHandler() {
int
count = 99;
ADC_Cmd(ADC1, DISABLE);
//ADC stop
//Send Sync
fputc_loc(0);
fputc_loc(10);
fputc_loc(100);
fputc_loc(101);
fputc_loc(103);
fputc_loc(7);
while
(count < 200) {
fputc_loc(ADCBuffer[count]);
// in conti- mode the first 100bytes are full of artifacts - I dont know why.
count++;
}
while
(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET){};
//GPIOC->ODR ^= GPIO_Pin_9; //just for checking the handler is working
ADC_Cmd(ADC1, ENABLE);
while
(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET) {}
ADC_SoftwareStartConv(ADC1);
//DMA1_IT_GL1: DMA1 Channel1 global interrupt.
DMA_ClearITPendingBit(DMA1_IT_GL1);
}
void
main() {
GPIO_outInit();
Timer2enable();//disable forcontinuousmode
//EnableTimerInterrupt();
ADC_IN18_DMA_INIT();
//START ADC (PB12)
while
(1);
}