AnsweredAssumed Answered

ADC artifacts in conti-mode STM32L100RC

Question asked by gerh.jo on Apr 29, 2015
Latest reply on May 4, 2015 by ash_

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 for continuous mode
//EnableTimerInterrupt();  
ADC_IN18_DMA_INIT(); //START ADC (PB12)
 
while(1);
}




Outcomes