Hallo,
ich habe einen XMega32A4U und möchte unter anderem die Versorgungsspanng
überwachen. Der ADC läuft durch (free run), DMA holt sich regelmäßig das
Ergebnis und legt es im RAM ab, das Hauptprogramm holt sich die Daten ab
und zu aus dem RAM zwecks Anzeige auf dem Display ab. Bis hierhin
funktioniert alles wunderbar. Nun wollte ich mittels des
Compare-Registers des ADC ein Interrupt auslösen lassen, sobald die
Spannungsversorgung einbricht (Brownout in Software). Wenn ich den
Interrupt aktiviere, funktioniert zwar der Interrupt zuverlässig, der
RAM bleibt aber leer (0x0000), sprich DMA funktioniert nicht. Scheint
als würden der Compare-Register des ADC und der DMA sich um das Ergebnis
streiten und der DMA ständig den kürzeren ziehen.
Kann das einer nachvollziehen? Gibt es ein Workaround? Habe ich einen
Fehler gemacht?
Hier meine Konfiguration (andere Kanäle weg gelassen, zum aktivieren des
Interrupt die auskommentierte Zeile aktivieren):
1 | ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | ADC_BANDGAP_bm | ADC_TEMPREF_bm;
|
2 | ADCA.EVCTRL = ADC_SWEEP_0123_gc;
|
3 | ADCA.PRESCALER = ADC_PRESCALER_DIV64_gc;
|
4 | ADCA.CTRLB = ADC_CONMODE_bm | ADC_FREERUN_bm;
|
5 | ADCA.CH3.CTRL = ADC_CH_INPUTMODE_INTERNAL_gc;
|
6 | ADCA.CH3.MUXCTRL = ADC_CH_MUXINT_SCALEDVCC_gc; // Vcc
|
7 | ADCA.CMP = 600; // Vcc below 3.0V
|
8 | //ADCA.CH3.INTCTRL = ADC_CH_INTMODE_BELOW_gc | ADC_CH_INTLVL_LO_gc;
|
9 |
|
10 | DMA.CTRL = DMA_ENABLE_bm;
|
11 | DMA.CH3.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc;
|
12 | DMA.CH3.SRCADDR0 = ((uint16_t)&ADCA_CH3_RES) & 0xff;
|
13 | DMA.CH3.SRCADDR1 = (uint16_t)&ADCA_CH3_RES >> 8;
|
14 | DMA.CH3.DESTADDR0 = ((uint16_t)&vcc_raw) & 0xff;
|
15 | DMA.CH3.DESTADDR1 = ((uint16_t)&vcc_raw >> 8) & 0xff;
|
16 | DMA.CH3.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH3_gc;
|
17 | DMA.CH3.TRFCNT = 2;
|
18 | DMA.CH3.CTRLA = DMA_CH_ENABLE_bm | DMA_CH_REPEAT_bm | DMA_CH_SINGLE_bm | DMA_CH_BURSTLEN_2BYTE_gc;
|
19 |
|
20 | ADCA.CTRLA = ADC_ENABLE_bm;
|