Hi,
ich möchte mit einem ATXMega192A3U die Werte eines ADC-Channels (ADCA.CH0) in ein Array ablegen, getriggert durch einen Timer (TCC1).
Der ADC ansich funktioniert, der Timer auch (wenn ich den OVF des Timers nutze).
Der Timer Period Wert ist auf 1000 gesetzt, das ergibt bei einem Prescaler = 1 einen (virtuellen) Timer-OVF alle 31.25us (bei 32MHz). TRFCNT ist auf 64 gesetzt, das sollte dann einen Transaction Complete Interrupt alle 2ms geben.
Leider hab ich wohl irgendwo einen Fehler drin, kann ihn aber nicht finden. Vielleicht fällt euch ja was auf:
Die SendPCUart-Routine schreibt ein "a" über die USART, das sollte eigentlich alle 0.002s * 250 (ReglerTimerCnt) = 0.5s erfolgen, kommt aber wesentlich öfter (wie oft genau kann ich nicht sagen, geschätzt wohl 500-5000 mal pro sekunde (ich weiß, ist keine wirkliche Angabe, aber es reicht, um sagen zu können, dass was falsch läuft).Code:void InitDmaCh3(void) { DMA.CH3.REPCNT = 0; //unlimited repeat DMA.CH3.CTRLA = 0xA5; //CH enable, repeat enabled, singleshot enabled, 2byte burst DMA.CH3.CTRLB = 0x01; //Channel Transaction Complete Lvl = Low DMA.CH3.ADDRCTRL = 0x9D; //SAR=Burst,SAM=INC,DAR=Transaction,DAM=INC DMA.CH3.TRIGSRC = 0x46; //TCC1 OVF DMA.CH3.TRFCNT = 64; //****************************** DMA.CH3.SRCADDR0 = (((uint32_t)(&ADCA.CH0.RES))>>0*8) & 0xFF; DMA.CH3.SRCADDR1 = (((uint32_t)(&ADCA.CH0.RES))>>1*8) & 0xFF; DMA.CH3.SRCADDR2 = (((uint32_t)(&ADCA.CH0.RES))>>2*8) & 0xFF; DMA.CH3.DESTADDR0 = (((uint32_t)(&AdcArray[0]))>>0*8) & 0xFF; DMA.CH3.DESTADDR1 = (((uint32_t)(&AdcArray[0]))>>1*8) & 0xFF; DMA.CH3.DESTADDR2 = (((uint32_t)(&AdcArray[0]))>>2*8) & 0xFF; } void InitAdcReglerTimer(void) { TCC1.CTRLA = 0x01; //Prescaler = 1 TCC1.CTRLB = 0x00; //Normal Mode TCC1.INTCTRLA = 0x00; //No Interrupt TCC1.PER = 1000; //31.25us (x 64 = 0.002) } ISR(DMA_CH3_vect) { DMA.CH3.CTRLB |= 0x10; //clear Interrupt flag ReglerTimerCnt++; if(ReglerTimerCnt>=250) { ReglerTimerCnt = 0; SendPCUart("a",1); } TimeElapsed += 1; TimerFlag = 1; AdcValue= 0; for(uint8_t i=0;i<64;i++) { AdcValue+= AdcArray[i]; } }
Vielen Dank & Gruß
Chris
EDIT:
Hab jetzt den "Fehler" gefunden: Wenn der Interrupt des Timers nicht ausgeführt wird, triggert er andauernd den DMA, weil anscheinand das OVF-Bit nicht zurückgesetzt wird.
Gibts eventuell eine Möglichkeit, das zu umgehen? Ansonsten bringt mir der DMA in diesem Fall garnichts, mir gehts ja darum, den Interrupt des Timers zu umgehen.
EDIT2:
Hab jetzt die Lösung (eine sehr gute sogar):
Ich verwende das EventSystem als Trigger, dieses kann man mit einem Prescaler konfigurieren. Hab jetzt 1024 gewählt, damit stimmt das Timing zwar nicht 100%, aber die paar us sind nicht so schlimm. Außerdem hab ich jetzt wieder einen Timer frei.







Zitieren

Lesezeichen