Forum: Mikrocontroller und Digitale Elektronik ADC ATXMega macht Probleme beim Umschalten des Kanals


von MOBA 2. (Gast)


Lesenswert?

Hi miteinander,

ich habe einen ATXMega256A3, er steuert als I²C-Slave ein Touchscreen 
(resistiv).

Ich bin soweit vom ATXMega begeistert, es klappte auch alles wunderbar - 
das einzige was bisschen komisch ist, ist der ADC. Erstmal verstehe ich 
das Datenblatt nicht so 100% mit CH0-CH3 und was dort möglich ist - 
soweit wie ich das Datenblatt verstanden habe, habe ich mir 2 Funktionen 
für den ADC geschrieben. Ich nutze nur die ADC-Portpins auf PORTB (ADC1, 
ADC2 für Touch, ADC4 für LDR). Jetzt kommt der Trick: Wenn ich einen 
Kanal dauerhaft auslese funktioniert es wunderbar, wie beim ATMega 
gewohnt werde die Werte sauber auf dem Display dargestellt (gilt für 
jeden ADC-Pin). Ich takte mit 32MHz int. Osc.

In der Main lese ich alle 10ms den Touch aus, dabei erst horizontal, 
danach vertikal. Ich schalte den ADC-Readpin einfach um. Als ich das 
gemacht habe, hat er nicht mehr funktioniert (gab immer 4095 aus) - erst 
als ich die Auslesezeit auf 100ms gesetzt habe (aus Zufall 
herausgefunden) klappte es - jedoch hat er, die Kanäle vertauscht?! Dann 
bin ich hergegangen, und habe 30ms horizontal, nach weiteren 30ms 
vertikal - jetzt klappt das schonmal für den Touch ordnungsgemäß, obwohl 
ich das Phänomen nicht verstehe.

Jetzt wollte ich noch den LDR (ADC4) alle 2sek. einlesen - jetzt ist er 
überfordert! Touch funktioniert, beim LDR kommt irgendein Quark raus 
(meist so um die 300). Wenn ich den Touch deaktiviere, und nur noch den 
LDR auslese, klappt es allerdings hervorragend?!!!?

Ich bin überfragt, das war beim ATMega schöner :(.

Nachfolgend mal meine 2 Funktionen, ich rufe diese in der Main einfach 
nach gew. Zeit auf, der "ADC_FEATURE_READ" Funktion übergebe ich den 
einzulesenden Port (bspw 1 für ADC1 (TouchX), 2 für ADC2 (TouchY) und 4 
für ADC4 (LDR).

1
void ADC_init(void)
2
{
3
  //ADC inits
4
  if (QUARZ_16MHZ)
5
    ADCB.PRESCALER=ADC_PRESCALER_DIV8_gc;  //Max. ADC Sampling 2MSPS (16MHz/8=2MSPS)
6
  else
7
    ADCB.PRESCALER=ADC_PRESCALER_DIV16_gc;  //Max. ADC Sampling 2MSPS (32MHz/16=2MSPS)
8
  
9
  ADCB.REFCTRL=ADC_REFSEL_AREFA_gc;      //AREF as REF (Ub MC)
10
  ADCB.CTRLB=ADC_RESOLUTION_12BIT_gc;
11
  ADCB.CH0.CTRL=ADC_CH_INPUTMODE_SINGLEENDED_gc;  //nur positiv
12
  ADCB.CTRLA=ADC_ENABLE_bm;  
13
}
14
15
uint16_t ADC_FEATURE_READ(uint8_t adc_portB)  
16
{
17
  if (adc_portB>7)
18
    return (adc_portB);
19
          
20
  ADCB.CH0.MUXCTRL=(adc_portB<<3);  //Port wählen //schieben, da nur positiv nehmen
21
  ADCB.CH0.CTRL |= (1<<ADC_CH_START_bp); //start conversion
22
  wdt_reset();
23
      
24
  while (!ADCB.CH0.INTFLAGS)
25
    wdt_reset();
26
      
27
  ADCB.CH0.INTFLAGS=0;  //Clear Bit (don't know if hardware do that)
28
29
  return (ADCB.CH0.RES);        //gebe das Ergebnis zurück  (ADCW) hier nochmals gucken wg. Registern  
30
}


Kleiner Nachtrag:

ich habe gerade herausgefunden, dass wenn ich den LDR 2-3mal auslese das 
es dann funktioniert (gilt auch für die Touch's). Jetzt bin ich komplett 
verwirrt - das irgendwie nicht ganz original, oder?

von Johann (Gast)


Lesenswert?

Hier ist schon mal ein  Fehler

 ADCB.CH0.INTFLAGS=0;  //Clear Bit (don't know if hardware do that)

Das Interruptfalg wird gelöscht, indem eine 1 geschrieben wird. Siehe 
Datenblatt


ADCA.CH0.INTFLAGS = ADCA.CH0.INTFLAGS;

von Johann (Gast)


Lesenswert?

Oh ich hatte übersehn das Du nicht ADC A sonder ADC B benutzt

ADCB.CH0.INTFLAGS = ADCB.CH0.INTFLAGS;

von MOBA 2. (Gast)


Lesenswert?

Hi,

das scheint es schon gewesen zu sein :o

Der Rest vom Quellcode scheint aber so korrekt zu sein, wa?

Mal eine Frage: ADCB.CH0.INTFLAGS = ADCB.CH0.INTFLAGS;   //was bringt 
das?

von Johann (Gast)


Lesenswert?

Die Zeile

ADCB.CH0.INTFLAGS = ADCB.CH0.INTFLAGS;

löscht das Interruptflag von ADC Channel 0


Bei Registern die das Interruptflag löschen muss man sich merken das man 
das FLAG nicht löscht indem Du eine 0 in dieses Register schreibst, 
sondern eine 1.

Dies steht auch im Datenblatt so drin.

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.