cancel
Showing results for 
Search instead for 
Did you mean: 

ADC artifacts in conti-mode STM32L100RC

jogerh
Associate II
Posted on April 29, 2015 at 23:18

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);
}

3 REPLIES 3
raptorhal2
Lead
Posted on April 30, 2015 at 16:26

Not sure what you mean by ''artifacts''. The DMA starts filling regular conversion values starting at location 0 in the buffer, and fills up to location 199, so there will be something in the first 100 locations also.

Read the ADC section describing DMA usage in the Reference Manual. There is no mention of being able to use DMA for injected channels. Injected conversions have 4 dedicated registers, and the results have to be read directly, i.e., no DMA.

Cheers, Hal

jogerh
Associate II
Posted on May 03, 2015 at 16:43

Thank you very much for responding.

“Artifact�? means a series of e.g. two spikes in the data stream I receive from the controller – however now I doubt this artifact is generated by the UART transmission itself – however I haven’t found yet why this is happening. Probably my software on the PC is not working correctly which I use to visualize the data. 

bzlybovz
Associate II
Posted on May 04, 2015 at 02:19

DMA_InitStructure.DMA_BufferSize = 

sizeof

(ADCBuffer); 

//buffersize
It should be sizeof(ADCBuffer) / sizeof(ADCBuffer[0])