Hi XMega Experten,
ich habe folgenden Testaufbau:
XMegaA4U, ein Poti zwischen GND und 3.2V VCC, Abgriff des Potis an ADC
positiven Pin. An AREF 1.6V. Negativer Pin des ADCs geht ebenfalls an
1.6V.
Software konfiguriert den ADC differentiell, vorzeichenbehaftet und 1x
Gain. Per Software gebe ich den gemessenen ADC Wert direkt ohne
Konvertierungen an einen der DACs aus.
Mit anderen Worten: per Poti kann ich an den positiven ADC Eingang eine
Spannung von 0 bis 3.2 Volt einstellen und am negativen Eingang liegen
immer 1.6V, also ARef, an.
Das verwirrende ist nun:
Bei Spannungen am Poti < 800mV gibt der DAC 0V = Wert 0 aus.
Bei Spannungen am Poti > 2.4V gibt der DAC 3.2V = Wert 4095 aus.
Bei Spannungen am Poti von ARef -+ARef/2 = 1.6V +-800mV = 800mV bis 2.4V
gibt der DAC Spannungen von 0V bis 3.2V aus.
Dabei ändert sich der DAC Wert linear ohne Sprünge. Die sich ergebende
Transferfunktion würde damit lauten:
Res = (INP - 1.6V/2)/1.6V * 4096;
oder eben
Res = (INP - AREF/2*GAIN)/AREF * 4096;
Nun hieße dies das die ADC Transferfunktion aus dem Datenblatt falsch
ist, sowie fast alle Angaben in den Datenblättern. Im datenblatt steht:
Res = (INP - INN)/AREF *GAIN *2048;
ergo:
Res = (INP - 1.6V)/1.6V *1 *2048;
Ändere ich den Gain auf 0.5x dann kann ich mit dem Poti den kompletten
0V bis 3.2V Spannungsbereich überstreichen und der DAC zeigt am Ausgang
ebenfalls proportional zur Potispannung 0V bis 3.2V an, ebenfalls ohne
Sprünge oder Saturation.
Alles sieht so aus als ob der ADC vorzeichenlos arbeiten würde obwohl
ich alles korrekt initialisiert habe.
Kennt einer von euch dieses Problem oder könnte mich über meinen evtln.
Denkfehler aufklären ?
Anbei die wichtigsten Sourcestücken.
1 | // DACB
|
2 | DACB.EVCTRL = DAC_EVSEL_6_gc;
|
3 | DACB.CTRLC = DAC_REFSEL_AVCC_gc;
|
4 | DACB.CTRLB = DAC_CHSEL_DUAL_gc | DAC_CH0TRIG_bm | DAC_CH1TRIG_bm;
|
5 | DACB.CTRLA = DAC_ENABLE_bm | DAC_CH0EN_bm | DAC_CH1EN_bm;
|
6 |
|
7 | // ADCA, 1 Kanal, 1.6V AREF and AREF.PORTA = ADC0 Pin
|
8 | ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN6_gc | ADC_CH_MUXNEG_PIN0_gc;
|
9 | ADCA.CH0.CTRL = ADC_CH_INPUTMODE_DIFFWGAIN_gc | ADC_CH_GAIN_1X_gc;
|
10 |
|
11 | ADCA.PRESCALER = ADC_PRESCALER_DIV32_gc;
|
12 | ADCA.EVCTRL = ADC_EVSEL_7_gc | ADC_SWEEP_0_gc | ADC_EVACT_SWEEP_gc;
|
13 | ADCA.REFCTRL = ADC_REFSEL_AREFA_gc; // 1.6V
|
14 | ADCA.CTRLB = ADC_IMPMODE_bm | ADC_CURRLIMIT_NO_gc | ADC_RESOLUTION_12BIT_gc;
|
15 | ADCA.CTRLA = ADC_ENABLE_bm;
|
16 |
|
17 | // DMA
|
18 | DMA_CH_t* CH;
|
19 |
|
20 | CH = &DMA.CH0;
|
21 | CH->SRCADDR0 = (uint8_t)((uint16_t)&DAC_data);
|
22 | CH->SRCADDR1 = (uint8_t)((uint16_t)&DAC_data >> 8);
|
23 | CH->SRCADDR2 = 0;
|
24 | CH->DESTADDR0 = (uint8_t)((uint16_t)&DACB.CH0DATA);
|
25 | CH->DESTADDR1 = (uint8_t)((uint16_t)&DACB.CH0DATA >> 8);
|
26 | CH->DESTADDR2 = 0;
|
27 | CH->ADDRCTRL = DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc;
|
28 | CH->TRFCNT = sizeof DAC_data;
|
29 | CH->REPCNT = 0;
|
30 | CH->TRIGSRC = DMA_CH_TRIGSRC_DACB_CH0_gc;
|
31 | CH->CTRLA = DMA_CH_ENABLE_bm | DMA_CH_REPEAT_bm | DMA_CH_SINGLE_bm | DMA_CH_BURSTLEN_4BYTE_gc;
|
32 |
|
33 | CH = &DMA.CH1;
|
34 | CH->SRCADDR0 = (uint8_t)((uint16_t)&ADCA.CH0RES);
|
35 | CH->SRCADDR1 = (uint8_t)((uint16_t)&ADCA.CH0RES >> 8);
|
36 | CH->SRCADDR2 = 0;
|
37 | CH->DESTADDR0 = (uint8_t)((uint16_t)&ADC_data);
|
38 | CH->DESTADDR1 = (uint8_t)((uint16_t)&ADC_data >> 8);
|
39 | CH->DESTADDR2 = 0;
|
40 | CH->ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc | DMA_CH_DESTDIR_INC_gc;
|
41 | CH->TRFCNT = sizeof ADC_data;
|
42 | CH->REPCNT = 0;
|
43 | CH->TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc;
|
44 | CH->CTRLA = DMA_CH_ENABLE_bm | DMA_CH_REPEAT_bm | DMA_CH_SINGLE_bm | DMA_CH_BURSTLEN_2BYTE_gc;
|
45 |
|
46 | while (1) {
|
47 | WAIT_FOR();
|
48 | int16_t adc = ADC_data[0];
|
49 | DAC_data[0] = adc;
|
50 | DAC_data[1] = adc;
|
51 | }
|
Gruß Hagen