Forum: Mikrocontroller und Digitale Elektronik ADC Werte mit DMA verwalten AVR XMega


von Thorsten (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe einen ATxMega128A1. Dort benutze ich den ADC und möchte nun, 
dass der DMA im Hintergrund, die Werte in den Speicher ablegt, damit ich 
diese nach und nach weiterverarbeiten kann.

Den ADC habe ich programmiert und den DMA auch, aber leider tut 
letzterer nicht was er soll. Ich möchte das die Quelle (ADC) immer die 
selbe ist und das Ziel ist ein array[1000] die Zieladdresse soll also 
immer inkrementiert werden.
Da ich den 12Bit ADC habe, habe ich den BurstMode auf 2Byte gestellt und 
´möchte dass der DMA alle 100 Byte wieder von vorne anfängt.

Den aktuellen Quellcode habe ich angehangen.(ADC ist auch mit dabei, 
vielleicht liegt hier auch der Fehler)
Es wäre sehr schön, wenn jemand der sich da auskennt mal drüber schaut 
(ist nicht viel code) und mir einen tipp gibt, wo mein Fehler liegen 
könnte.

Danke für Eure Mühen

Viele Grüße

Thorsten

von Gerhard G. (g_g)


Lesenswert?

Hallo,

schau dir mal meine Homepage-Seite an:

http://www.basteln-mit-avr.de/atxmega128a3.html#adc_dma

Hier findest du einen ADC/DMA Vorgang der funktioniert.

Teste das mal und erweitere dann deinen Code.

Gruß G.G.

von Thorsten (Gast)


Lesenswert?

Hallo, danke ersteinmal.

ich habe es mir angeguckt und es sieht bei mir auch sehr ähnlich aus. 
Eben auf mein Projekt zugeschnitten (nur ein Channel und ich benutze 
auch keine Interrupts).

Ich bekomme inzwischen auch Werte in meinem Speicherarray, nur sind 
diese viel zu groß. (im Bereich von 40000-60000) Obwohl mein ADC nur 
Werte zwischen 0-4096 erzeugt. Woran könnte das liegen? Ein Überlauf?
Wie finde ich das herraus?

Danke und Gruß

Thorsten

von Jens (Gast)


Lesenswert?

Wird high und low-Byte in der richtigen Reihenfolge abgelegt? Sind die 
vielleicht vertauscht?

von Thorsten (Gast)


Lesenswert?

Moin,
ich denke nicht.
        DMA.CH0.DESTADDR0 = ((uint32_t) array >>0*8)&0xFF;
  DMA.CH0.DESTADDR1 = ((uint32_t) array >>1*8)&0xFF;
  DMA.CH0.DESTADDR2 = ((uint32_t) array >>2*8)&0xFF;
So habe ich den DMA initialisiert. Genauso wie die source.
Und der Zugriff erfolgt doch über array?
heißt, wenn ich wissen will was er nun gespeichert hat:

uint16_t ergebnis = array[0];     //in ergebnis steht der erste Wert, 
den
                                    der DMA geschrieben hat

Richtig soweit?

von Thorsten (Gast)


Lesenswert?

Bin leider immer noch nicht weiter.
Kennt sich denn keiner mit dem DMA aus??

von holger (Gast)


Lesenswert?

//8Bit Ergebnis in array
  DMA.CH0.DESTADDR0 = ((uint32_t) array >>0*8)&0xFF;
  DMA.CH0.DESTADDR1 = ((uint32_t) array >>1*8)&0xFF;
  DMA.CH0.DESTADDR2 = ((uint32_t) array >>2*8)&0xFF;


Ich würde da mal Klammern setzen:

  DMA.CH0.DESTADDR0 = ((uint32_t) array >>(1*8))&0xFF;

: Wiederhergestellt durch Moderator
von Thorsten (Gast)


Lesenswert?

Hallo zusammen,

also so sieht der aktuelle Quelltext aus:


______________________________________________________________
DMA.CH0.CTRLA = DMA_ENABLE_bm;
  DMA.CTRL = DMA_ENABLE_bm;


  //Modus Transaktion, increase und fix, Burst
  DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_NONE_gc | DMA_CH_SRCDIR_FIXED_gc| 
DMA_CH_DESTRELOAD_TRANSACTION_gc | DMA_CH_DESTDIR_INC_gc;

  // Trigger Source ist ADCA Triggerung wenn der Datenpuffer leer ist.
  DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc;

  //100 Byte sind zu übertragen!
  DMA.CH0.TRFCNT = 20;    //nur 2 byte
  //DMA.CH0.CTRLA |= 0x10;

  //Repeat in Endlosschleife
  DMA.CH0.REPCNT = 0;      //endlosschleife
  DMA.CH0.CTRLA |= DMA_CH_BURSTLEN_2BYTE_gc | DMA_CH_REPEAT_bm 
|DMA_CH_SINGLE_bm;    //repeat Bit setzten 2Byte  BurstLength , 
singleshot
  //DMA.CH0.CTRLA |= 0x01;    //no repeat 2Byte BurstLength
                                  //evtl noch single shot bit in CTRLA 
|= 0x04 setzten


  //16Bit Quelle
  DMA.CH0.SRCADDR0  =(((uint16_t)(&ADCA.CH0.RES))>> 0*8);
  DMA.CH0.SRCADDR1  =(((uint16_t)(&ADCA.CH0.RES))>> 1*8);
  DMA.CH0.SRCADDR2  = 0;

  //16Bit Ergebnis in array
  DMA.CH0.DESTADDR0 = ((uint16_t) array >> (0*8));
  DMA.CH0.DESTADDR1 = ((uint16_t) array >> (1*8));
  DMA.CH0.DESTADDR2 = 0;

_________________________________________________________________

An den Klammern lags nicht.
Wenn ich in den Speicher reingucke, schreibt er immer so doppelpaare in 
den Speicher. z.B.
a3a3 3434 f7f7 1919 usw.

es scheint fast, als ob nur ein Byte übertragen wird, aber 
2-Byte-Burst-Mode ist ausgewählt.
Ich weiß keine Erklärung und hoffe hier ist jemand der mir da 
weiterhelfen kann.

Gruß
Thorsten

von Alexander V. (avogra)


Lesenswert?

hi,
ich hab nur mal drüber geflogen, aber wenn ichs richtig seh, liest du 
immer die gleiche src-adresse aus. das sind ja dann vom adc das erste 
byte. nachdem der adc aber 2byte lange werte zurückliefert, musst du den 
src-mode nicht auf fixed, sondern auf inc stellen. damit die nächste 
messung wieder beim ursprung anfängt, schaltest du noch src-reload ein, 
so dass der adc nach dem 2ten adc-byte die src-adresse wieder auf das 
erste adc-byte zurückschaltet.

War jetzt nur ganz kurz aus m Gedächtnis, aber ich hoff, der 
Gedankengang kommt rüber :)

Viele Grüße,
Alex

von Alexander V. (avogra)


Lesenswert?

Schau dir mal hier http://www.atmel.com/Images/doc8046.pdf den Punkt 3.3 
an. Das müsste genau das sein, was du willst.

Gruß, Alex

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.