AnsweredAssumed Answered

ADC /DMA  Problem STM32F100

Question asked by M G on Sep 18, 2017
Latest reply on Sep 26, 2017 by M G

ADC1 converts  every 500us 5 analog channels ( ADC10/11/12/13/14) and write the result via DMA1 to internal SRAM  (ADResult[5]) in this order [ ADC10,ADC11,ADC12,ADC13,ADC14]. This works fine, but randomly after some houres or days the result order in memory is corrupted to [ADC14,ADC10,ADC11,ADC12,ADC13], shift at one Position  and stay in this wrong order all the time.


ADC1 is configured in Scan Mode, not continuous conversion:


// ADC Konfiguration (regular group = ADC10/11/12/13/14
  RCC->APB2ENR|=RCC_APB2ENR_ADC1EN;  //enable Clock for ADC1
  ADC1->SQR1=0x00400000;    //5 Kanäle
  ADC1->SMPR2=0x3fffffff;    //Abstastzeit der Kanäle auf 240 Zyklen
  ADC1->SQR3=0x1ee6b16a;    //Abtastreihenfolge festlegen 10/11/12/13/14
  ADC1->CR1=0x00000100;                 //use independant mode, SCAN mode
  ADC1->CR2=0x000e0100;     //use data align right,not continuous conversion
                                              // EXTSEL = SWSTART


DMA1 Configuration:

// DMA-Konfiguration für A/D-Wandler
  RCC->AHBENR|=RCC_AHBENR_DMA1EN;  // enable Clock for DMA1
  DMA1_Channel1->CMAR=(u32)ADValue;  // DMA-Zieladresse setzen
  DMA1_Channel1->CPAR=(u32)&(ADC1->DR); // DMA-Quelladresse setzen
  DMA1_Channel1->CNDTR=5;    // transmit 5 words
  DMA1_Channel1->CCR=0x00003580;  // DMA konfig. (0x00000580)
  DMA1_Channel1->CCR|=DMA_CCR1_EN;  // DMA Channel 1 enable


The ADC conversion is started in the  TIM2_IRQHandler(), which is called every 500us:



void TIM2_IRQHandler(void)

{ .......


   ADC1->SR&=~ADC_SR_EOC;       // Interrupt-Flag clear
   ADC1->CR2  |=  0x00500000;      // start A/D conversion (0x00500000)
   ADC1->CR1|=ADC_CR1_EOCIE;       // EOC-Interrupt enable



}After the A/D conversion of this 5 Inputs is finished  ADC1_IRQHandler/() is called. Tme between start A/D conversion

and call of ADC1_IRQHandler() is 100us.


void ADC1_IRQHandler(void)

  ADC1->SR&=~ADC_SR_EOC;     // Interrupt-Flag löschen
  ADC1->CR1&=~ADC_CR1_EOCIE;    // EOC-Interrupt sperren
  while(!(DMA1->ISR & 0x02UL));    // Warten auf Ende des DMA-Transfers
  DMA1->IFCR=0x02UL;      // Flag löschen
  //DMA-Transferzähler nachladen
  DMA1_Channel1->CCR&=~(1<<0);    // DMA Channel 1 disable
  DMA1_Channel1->CNDTR=5;     // transmit 5 words
  DMA1_Channel1->CCR|=(1<<0);    // DMA Channel 1 enable





Has anyone encountered a same Problem ?

Please help.