[solved] XMEGA ADC with DMA problem

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am configuring 2 DMA channels to acquire data from 2 ADC channels. I am using the ADC in signed mode. Data from ADCA.CH0 looks ok, but with ADCA.CH1, the sign bit is lost, results are always positive. When not using the DMA, the results are ok. If I swap the DMA channels, the problem stays with ADC.CH1.

Below is a portion of my code:

    // ADC
ADCA.CTRLA = 0x01;      // Enable ADC
ADCA.CTRLB  = 0x18;     // signed mode, free run, 12 bit
ADCA.REFCTRL =0x20;     // REF= AREF (2V)
ADCA.EVCTRL = 0x40;     // Sweep channels 0,1
ADCA.PRESCALER = 0x02;  // Prescaler 16 (2MHZ ADC clock)
ADCA.CH0.MUXCTRL = 0x2A;// Channel 0 input: ADC5 pin - ADC6 pin
ADCA.CH0.CTRL = 0x03;   // Differential input with gain
ADCA.CH1.MUXCTRL = 0x2B;// Channel 1 input: ADC5 pin - ADC7 pin
ADCA.CH1.CTRL = 0x03;   // Differential input with gain
ADCA.CH2.MUXCTRL = 0x02;// Channel 2 input: VCC/10
ADCA.CH2.CTRL = 0x00;   // Internal input
ADCA.CH3.MUXCTRL = 0x00;// Channel 3 input: temperature
ADCA.CH3.CTRL = 0x00;   // Internal input

// DMAs
DMA.CTRL = 0x80;        // Enable DMA, single buffer, round robin
// DMA for ADC CH0
DMA.CH0.ADDRCTRL  = 0b10010101;     // reload source addr after each burst, incr src/des, reload dest end block
DMA.CH0.TRIGSRC   = 0x10;           // ADCA CH0 is trigger source
DMA.CH0.TRFCNT    = 512;            // buffer size
DMA.CH0.DESTADDR0 = (((uint32_t) bigtemp)>>0*8) & 0xFF;
DMA.CH0.DESTADDR1 = (((uint32_t) bigtemp)>>1*8) & 0xFF;
DMA.CH0.DESTADDR2 = (((uint32_t) bigtemp)>>2*8) & 0xFF;
DMA.CH0.SRCADDR0  = (((uint32_t)(&ADCA.CH0.RES))>>0*8) & 0xFF;
DMA.CH0.SRCADDR1  = (((uint32_t)(&ADCA.CH0.RES))>>1*8) & 0xFF;
DMA.CH0.SRCADDR2  = (((uint32_t)(&ADCA.CH0.RES))>>2*8) & 0xFF;
DMA.CH0.CTRLA     = 0b00000101;     // no repeat, 2 byte burst 
// DMA for ADC CH1
DMA.CH1.ADDRCTRL  = 0b10010101;     // reload source addr after each burst, incr src/des, reload dest end block
DMA.CH1.TRIGSRC   = 0x11;           // ADCA CH1 is trigger source
DMA.CH1.TRFCNT    = 512;            // buffer size
DMA.CH1.DESTADDR0 = (((uint32_t)(bigtemp+512))>>0*8) & 0xFF;
DMA.CH1.DESTADDR1 = (((uint32_t)(bigtemp+512))>>1*8) & 0xFF;
DMA.CH1.DESTADDR2 = (((uint32_t)(bigtemp+512))>>2*8) & 0xFF;
DMA.CH1.SRCADDR0  = (((uint32_t)(&ADCA.CH1.RES))>>0*8) & 0xFF;
DMA.CH1.SRCADDR1  = (((uint32_t)(&ADCA.CH1.RES))>>1*8) & 0xFF;
DMA.CH1.SRCADDR2  = (((uint32_t)(&ADCA.CH1.RES))>>2*8) & 0xFF;
DMA.CH1.CTRLA     = 0b00000101;     // no repeat, 2 byte burst 

Can someone else try to replicate the problem?
Tomorrow I'll try to see what happens if I use the ADC in unsigned mode.

Last Edited: Fri. Jan 7, 2011 - 01:48 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Some suggestions that may help:

1- Enable ADC after register settings.
2- Try with only CH1 active and see results.
3- Reduce ADC clock.
4- Try single conversions instead of free running mode.

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It was a bug in my code. I had left the ADCA.CH0.INTCTRL register with a value of 0x0C (Interrupt Mode:Compare Result Above Threshold, which I needed for triggering purposes), but then made the DMA only acquire positive data. It was solved by clearing ADCA.CH0.INTCTRL after the trigger section.

Last Edited: Fri. Jan 7, 2011 - 02:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What device signals are you ADC'ing ? How are you biasing to get negative voltage swings ?

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ganzziani wrote:
I had left the ADCA.CH0.INTCTRL register with a value of 0x03 (interrupt when a value is above a threshold)

Loading ADCA.CH0.INTCTRL with 0x03 does not mean "interrupt when a value is above a threshold". It means "interrupt when conversion complete with a high level priority".

Ozhan KD
Knowledge is POWER

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

indianajones11 wrote:
What device signals are you ADC'ing ? How are you biasing to get negative voltage swings ?
I am developing an oscilloscope called Xprotolab. You can find the schematics at my website. But to answer your question, I shift the +/-2V to 0 to 2V with a voltage divider connected to +2V.
electronic.designer wrote:
Loading ADCA.CH0.INTCTRL with 0x03 does not mean "interrupt when a value is above a threshold". It means "interrupt when conversion complete with a high level priority".
Correct, I meant a value 0x0C (Interrupt mode is "Compare Result Above Threshold")