Forum: Mikrocontroller und Digitale Elektronik Messen mehrerer Spannung mit ADC/XMega


von Werner (Gast)


Lesenswert?

Hallo Leute.

Ich hätte eine Fragen zum Messen von mehreren Spannungen mit einem
XMega128A1.
Der XMega hat 2 ADC. Einmal den ADC am Port A und den zweiten am Port B.
Jeder ADC hat 4 Kanäle.
Ich möchte am Port A, am Pin 1 und Pin 4 bis Pin 7, Spannungen
(insgesamt 5) messen. An Pin 0 des Port A ist die
Referenzspannungsquelle angeschlossen.

Nun habe ich im ursprünglichen Programm mit dieser Funktion
1
uint16_t ADC_Conversion(ADC_CH_t *Channel, char Pin)
2
{
3
  Channel->CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
4
  Channel->MUXCTRL = (Pin << 3);
5
  Channel->CTRL |= ADC_CH_START_bm;
6
  while((Channel->INTFLAGS) == 0);
7
  return Channel->RES;
8
}
den ADCA mit den entsprechenden Pins abgefragt.
Ich spreche beim Funktionsaufruf immer den Kanal 0 des ADC an.

Letztlich erhalte ich für jeden Aufruf, egal welche Pins, immer das
gleiche Ergebnis. Liegt es daran, dass ich immer mit dem gleichen Kanal
arbeite, also muss ich bei jedem Aufruf einen anderen Kanal einsetzen
oder liegt der Fehler woanders? Nach meiner Auffassung sollte der im
Ergebnisregister des Kanals stehende Wert bei erneuten Aufruf der
Funktion überschrieben werden oder nicht?


Viele Grüße

von Alex (Gast)


Lesenswert?

Auf die Schnelle ist mir aufgefallen, dass du vergessen hast, das 
Interuptflag nach dem Auslesen auch wieder zu löschen.
Leider hast du deine ADC-Inititialisierung nicht angegeben.

PS: Die ADC's haben einige Macken - lese unbedingt die Errata dazu im 
XMegaxxxA1-Datasheet!!
Zum Beispiel auch, wenn du die Eingänge umschaltetst, musst du zuerst 
einige Werte wegwerfen!

von Werner (Gast)


Lesenswert?

Danke. Das ist mir gestern Abend noch selbst aufgefallen. :)


Meine Init:
1
void ADC_init(void)
2
{
3
  PORTA.DIR = PIN2_bm|PIN3_bm;
4
  
5
  ADCA.CTRLB = ADC_RESOLUTION_12BIT_gc;
6
  ADCA.REFCTRL = ADC_REFSEL_AREFA_gc;
7
  ADCA.PRESCALER = ADC_PRESCALER_DIV8_gc;
8
  ADCA.CTRLA = ADC_CH0START_bm|ADC_ENABLE_bm;
9
  
10
  ADC_Kalibrieren();
11
  
12
}

Die Errata habe ich schon gelesen. Ich habe nun unabhängig von meinem 
Problem eine Erweiterte Funktion geschrieben, in der mehrere Messungen 
durchgeführt werden und am Ende der Mittelwert gebildet wird.
1
uint16_t ADC_Read_Average (ADC_CH_t *Channel, char Pin )
2
{
3
  int  Mittelwert=0,
4
  Summe=0,
5
  i;
6
  
7
  for (i=0;i<=nSamples;i++)
8
  {
9
    Summe+=(ADC_Read(Channel, Pin)-204);
10
    if (i<3){Summe=0;}
11
  }
12
  
13
  Mittelwert=Summe/nSamples-3;
14
  if (Mittelwert>0x0FFF){Mittelwert=0;}
15
  return Mittelwert;
16
}

In der Errata habe ich etwas davon gelesen, dass beim Kanalwechsel die 
ersten drei Messresultate verworfen werden müssen. Auch wenn ich 
eigentlich nicht den Kanal wechsel, habe ich dies zur vorsicht in die 
Funktion integriert.

von Timmo H. (masterfx)


Lesenswert?

Beim schnellen umschalten ist die Sample and hold Schaltung noch nicht 
vollständig entladen.  Da sollte schon etwas Zeit einplanen

: 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.