1

I have STM8LDiscovery (with STM8L152C6T6 CPU). I need to continuously read 2 ADC channels with writing the data to the memory.

I'm doing my project in IAR EW for STM8 v. 3.11.4.

I run into the problem: channels data (ADC_DATA) continuously exchanging their places, so ADC_IN0 can be writen in either ADC_DATA[0] or ADC_DATA[1] and vice versa for ADC_IN1. Moreover: ADC overrun error (ADC1_SR.OVER) is apearing right after the start of the application and never go away.

Looks like ADC and DMA works not in the sync. As there is overrun error in the ADC status register I assume that DMA works slower than ADC producing the conversion data.

DMA writes exactly 2 words of memory. I already have tested it by increasing the ADC_DATA array size.

My ADC and DMA configuration looks like this:

  unsigned int ADC_DATA[10];

  // ADC1 clock enable
  CLK_PCKENR2_bit.PCKEN20 = 1;
  // DMA1 clock enable
  CLK_PCKENR2_bit.PCKEN24 = 1;

  // ADC1_IN0 (PA5): Input, No pull-up, Interrupt disable
  PA_DDR_bit.DDR5 = 0;
  PA_CR1_bit.C15 = 0;
  PA_CR2_bit.C25 = 0;
  // ADC1_IN1 (PA6): Input, No pull-up, Interrupt disable
  PA_DDR_bit.DDR6 = 0;
  PA_CR1_bit.C16 = 0;
  PA_CR2_bit.C26 = 0;
  
  // ADC1 conversion complete interrupt disabled
  ADC1_CR1_bit.EOCIE = 0;
  // ADC1 continuous conversion mode enabled
  ADC1_CR1_bit.CONT = 1;
  
  // ADC1 clock prescale 1:2
  ADC1_CR2_bit.PRESC = 1;
  
  // ADC1 sequence selection
  // PA6, PA5
  ADC1_SQR1 = 0x00;
  ADC1_SQR2 = 0x00;
  ADC1_SQR3 = 0x00;
  ADC1_SQR4 = 0x03;
  
  // DMA channel 0 in increment mode
  DMA1_C0CR_bit.MINCDEC = 1;
  // DMA channel 0 in circular mode
  DMA1_C0CR_bit.CIRC = 1;
  // DMA channel 0 in direction: peripheral to memory
  DMA1_C0CR_bit.DIR = 0;
  // DMA channel 0 interrupt disabled
  DMA1_C0CR_bit.TCIE = 0;
  // DMA channel 0 priority LOW
  DMA1_C0SPR_bit.PL0= 0;
  DMA1_C0SPR_bit.PL1= 0;
  // DMA channel 0 16-bit mode
  DMA1_C0SPR_bit.TSIZE= 1;
  // DMA number af words to transfer
  DMA1_C0NDTR = 2;
  // DMA channel 0 peripipheral address
  DMA1_C0PARH = 0x53;
  DMA1_C0PARL = 0x44;
  // DMA channel 0 memory address
  DMA1_C0M0ARH = (unsigned char)(((unsigned int)(&ADC_DATA[0])) / 256);
  DMA1_C0M0ARL = (unsigned char)(((unsigned int)(&ADC_DATA[0])) % 256);
  // DMA enabled
  DMA1_GCSR_bit.GEN = 1;
  // DMA channel 0 enabled
  DMA1_C0CR_bit.EN = 1;
  
  // ADC1 ON
  ADC1_CR1_bit.ADON = 1;
  // ADC1 start conversion
  ADC1_CR1_bit.START = 1;

What could be wrong with my code?

Roman Matveev
  • 2,942
  • 7
  • 32
  • 75
  • 1
    If you don't `volatile` qualify the buffer then very strange things might happen. Not necessarily the problem you are struggling with here, but it is a bug. – Lundin Mar 24 '23 at 07:49
  • @Lundin corrected that. But did not help – Roman Matveev Mar 24 '23 at 08:27
  • ADC over run occurs if the EOC flag is set when a value is written to the data register. Check the sequence required to clear the flag and make certain that the DMA is doing it. Also check the sequence required to clear the OVRN flag. – RussellH Mar 28 '23 at 18:12
  • @RussellH, I don't know actually how to reset the EOC flag if the data is transfered with DMA (no CPU core involved). My assumption was that DMA should take care of all this things as it takes the data off the ADC. – Roman Matveev Mar 28 '23 at 19:23

0 Answers0