Forum: Mikrocontroller und Digitale Elektronik ATXMega 16D4 - Probleme mit ADC


von Nico (Gast)


Lesenswert?

Hallo Forum,

ich sitze nun schon den ganzen daran den ADC des Xmega ans laufen zu 
kriegen. Werte einlesen klappt einwandfrei, dafür hab ich ca. 0,5V 
Versatz zu meiner Referenzspannung. Diese ist eingestellt auf INTVCC - 
Vcc/1.6, sollte also mit Vcc = 3V bei 1,875V liegen. Jedoch bekomme ich 
bereits bei 1,3V am ADC den vollen Wert angezeigt.

Mit einer externen Referenz von 2,4V funktioniert alles einwandferei.

Hier der Code:
1
#include <avr/io.h>
2
#include <stddef.h>
3
#include <avr/pgmspace.h>
4
5
unsigned int ADCA_Conversion(ADC_CH_t *Channel, char Pin);
6
void ADCA_init(void);
7
void ADCA_Cal(void);
8
int LeseKalibrationsbyte(int Index);
9
10
unsigned int ADC_value1;
11
12
unsigned int test_buffer[100];
13
unsigned int test_count;
14
15
16
int main(void)
17
{
18
   PORTB.DIR = 0x00;
19
   ADCA_init();
20
   ADCA_Cal();
21
   
22
   
23
    while(1)
24
    {
25
        ADC_value1 =  ADCA_Conversion(&(ADCA.CH0), 9);    //PB1
26
    
27
    test_buffer[test_count] = ADC_value1;
28
    test_count++;
29
    
30
    if(test_count >= 100)
31
      test_count = 0;
32
    }
33
}
34
35
36
//******************************init ADC*****************************//
37
void ADCA_init(void)
38
{
39
  ADCA.CTRLB = ADC_RESOLUTION_12BIT_gc;  //12Bit
40
  ADCA.REFCTRL = 0x20;          //INTVCC - Vcc/1.6
41
  ADCA.PRESCALER = 0x04;          //DIV64
42
  ADCA.CTRLA = 0x01;            //Enable ADC
43
}
44
45
46
//******************************do ADC******************************//
47
unsigned int ADCA_Conversion(ADC_CH_t *Channel, char Pin)
48
{
49
  ADCA.CH0.RES = 0;
50
  ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
51
  ADCA.CH0.MUXCTRL = (Pin << 3);
52
  ADCA.CH0.CTRL |= ADC_CH_START_bm;
53
    
54
  while(!Channel->INTFLAGS);
55
  return ADCA.CH0.RES;
56
}
57
58
59
//******************************cal ADC*****************************//
60
void ADCA_Cal(void)
61
{
62
   ADCA.CALL =
63
   LeseKalibrationsbyte(offsetof(NVM_PROD_SIGNATURES_t,    
64
   ADCACAL0));
65
   ADCA.CALH =
66
   LeseKalibrationsbyte(offsetof(NVM_PROD_SIGNATURES_t,    
67
   ADCACAL1));
68
}
69
70
71
//****************************r_cal ADC******************************//
72
int LeseKalibrationsbyte(int Index)
73
{
74
   int result;
75
76
   NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
77
   result = pgm_read_byte(Index);
78
   NVM_CMD = NVM_CMD_NO_OPERATION_gc;
79
   return(result);
80
}

Vielleicht hab ich was übersehen und jemand hat ne Idee?

Gruß,
Nico

von Thomas F. (tomasf)


Lesenswert?

Das kommt davon, dass man nicht die vorgegebenen Konstanten für die 
Register nimmt...

ADCA.REFCTRL = 0x20;

vs

ADC_REFSEL_VCCDIV2_gc = (0x04<<4),  /* Internal VCC / 2 */


PS: beim xmegaD4 auf die Revision achten, der ADC hat Bugs in älteren 
Revisionen.

von Nico (Gast)


Lesenswert?

Hallo Thomas,

Danke für die Antwort. Die Bug-Geschichte habe ich mir mal angeschaut. 
Leider deutet da nichts auf das oben genannte Phänomen hin.

Was mir nicht ganz klar ist, warum die vorgegebenen Konstanten verwendet 
werden sollen, außer dass dadurch die Übersichtlichkeit verbessert wird?

Sicher ist oben noch ein Fehler im Code, da ADCA.REFCTRL = 0x20 die 
externe Referenz einstellt und nicht die Vcc/1.6. Das hatte ich beim 
Testen nicht geändert. Aber irgendwie hab ich das Gefühl mit dem ADC 
stimmt irgendwas nicht. Werd mal nen zweiten µController testen.

von Karl H. (kbuchegg)


Lesenswert?

Nico schrieb:

> Was mir nicht ganz klar ist, warum die vorgegebenen Konstanten verwendet
> werden sollen, außer dass dadurch die Übersichtlichkeit verbessert wird?

Alleine das ist doch schon Grund genug.

> Sicher ist oben noch ein Fehler im Code, da ADCA.REFCTRL = 0x20 die
> externe Referenz einstellt und nicht die Vcc/1.6.

Siehste. Mit den vordefinierten Konstanten wär dir das nicht passiert.

von Thomas F. (tomasf)


Lesenswert?

Ok, wenn die Referenz richtig eingestellt ist, muss es was anderes sein.

Ein gewisses Offset ist zu erwarten. Bie den Xmegas ist das etwa 5%, bei 
denen mit verbugten ADC kann es auch mehr sein. Das muss man auch auf 
jeden Fall rausrechnen. Aber 0,5V ist dafür zuviel.

: Bearbeitet durch User
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.