Forum: Mikrocontroller und Digitale Elektronik Nur einmaliges init vom ADC?


von Karsten K. (karsten42)


Lesenswert?

Moin Moin,

Entschuldigt bitte diese Frage. Ich habe natürlich die Suchfunktion 
vorher benutzt :-)
ENV:
ATmega8, WIN-AVR-20100110

Reicht es aus den ADC nur einmalig für folgende single conversion auf 
verschiedenen Kanälen mit der "dummy conversion" zu initialisieren? Laut 
Datenblatt sind die verschiedenen Kanäle eines ADC über einen MUX 
aufgeteilt und so sollte eine einmalige initialisierung ausreichen. Ich 
bin mir da aber nicht zu 100% sicher.
ADC_init() wird im main vor der main-loop aufgerufen und rd_ADC() dann 
n-mal für verschiedene Kanäle in der main-loop.
1
#define ADC_LOOP 128
2
3
void
4
ADC_init(void)  {
5
6
  uint8_t result;
7
 
8
  // External Vref, single conversion (default set ADMUX reg)
9
  // Left adjusted result in ADCH for 8 bit result
10
  ADMUX |= (1<<ADLAR);  
11
  
12
  // Enable ADC, 250Khz ADC clock
13
  ADCSRA |= (1<<ADEN) |(1<<ADPS2) | (1<<ADPS0);
14
15
  // Initial conversion for warm up
16
  ADCSRA |= (1<<ADSC);
17
  while (ADCSRA & (1<<ADSC) );
18
  result = ADCH;
19
}
20
21
uint8_t
22
rd_ADC(uint8_t channel)  {
23
24
  uint16_t result = 0;
25
  uint8_t cnt = 0;
26
27
  ADMUX |= (1<<channel);
28
29
  // run conversion ADC_LOOP times and build averange
30
  for(cnt = 0; cnt <= ADC_LOOP; cnt++)  {
31
32
    ADCSRA |= (1<<ADSC);
33
    while (ADCSRA & (1<<ADSC) );
34
    result += ADCH;
35
  }
36
37
  result /= ADC_LOOP;
38
  ADMUX &= ~(1<<channel);
39
40
  return (uint8_t)result;
41
}

Danke für eure Geduld!

Gruß
Karsten

von Karl H. (kbuchegg)


Lesenswert?

Karsten K. schrieb:


> Reicht es aus den ADC nur einmalig für folgende single conversion auf
> verschiedenen Kanälen mit der "dummy conversion" zu initialisieren? Laut
> Datenblatt sind die verschiedenen Kanäle eines ADC über einen MUX
> aufgeteilt und so sollte eine einmalige initialisierung ausreichen. Ich
> bin mir da aber nicht zu 100% sicher.

Tut es.
Das Verwerfen des ersten Messergebnisses wird von Atmel nach der 
Aktivierung des ADC empfohlen.

von Karl H. (kbuchegg)


Lesenswert?

1
rd_ADC(uint8_t channel)  {
2
3
  ...
4
5
  ADMUX |= (1<<channel);
6
7
  ...
8
9
  ADMUX &= ~(1<<channel);

keine gute Lösung.
Du musst dir im klaren sein, dass hier den ADC nicht 'abschaltest', 
sondern immer wieder auf den Kanal 0 zurückschaltest. D.h. wenn dein 
Programm den Kanal 5 (und nur den Kanal 5) abfrägt, schaltest du 
zwischendurch immer wieder auf Kanal 0 zurück. Das bedeutet aber auch, 
dass sich die Sample&Hold Stufe am ADC Eingang immer wieder auf einen 
anderen Spannungswert einstellen muss, was unter Umständen (je nach 
Impedanz der angeschlossenen Schaltung) eine zeitlang dauern kann.

Es hat schon seinen Grund, warum das im AVR-GCC-Tutorial anders 
gelöst ist.

von MWS (Gast)


Lesenswert?

Würd' empfehlen ein erstmalig beschriebenes Register in einer 
Init-Routine nicht zu verodern.

Sollte aus irgendeinem Grund ein erneuter Aufruf der Init sinnvoll sein, 
werden sonst alte Registerinhalte übernommen.

von Karsten K. (karsten42)


Lesenswert?

Moin Moin

Wahhh, das ging schnell!  Daaanke!
1
ADMUX |= (1<<channel);
2
3
  ...
4
5
ADMUX &= ~(1<<channel);

Das solle auch nicht den ADC ausschalten sondern nur sicher stellen, 
dass nur der an rd_ADC() übergebene Kanal ausgelesen wird. Natürlich 
hast du recht, dass die S&H bei jedem MUX-switch etwas Zeit benötigt. Im 
Datenblatt steht, dass eine Ausgangsimpedanz des zu messenden Signales < 
10K sein sollte um beste Ergebnisse zu erreichen. Soweit ich das erkenne 
hat der C in der S&H nur 14p sodaß sie Ladezeit recht schnell sein wird 
( interner R ist mir 1-100K angegeben??) Zumal ich auch nur alle 100ms 
mal messen möchte.

Herzlichen Dank für die Antworten und Tips!!!

Gruß
Karsten

von Karl H. (kbuchegg)


Lesenswert?

Karsten K. schrieb:

> Das solle auch nicht den ADC ausschalten sondern nur sicher stellen,
> dass nur der an rd_ADC() übergebene Kanal ausgelesen wird.

Der springende Punkt ist, dass man das ganze auch so lösen kann, dass 
der MUX nur dann umgeschaltet wird, wenn es tatsächlich notwendig ist. 
Der Aufwand dafür hält sich in Grenzen.

  ADMUX = ADMUX & ~0x0F | channel;


Ausserdem fällt mir gerade auf, dass du an dieser STelle kein 
(1<<channel) haben willst. Im MUX Register ist die Kanaleinstellung 
nicht bitkodiert, sondern das sind ganz normale Binärzahlen. Um den 
Kanal 5 einzustellen, wird das Bitmuster 0101 (also eine binäre 5) an 
die MUX Bits zugewiesen.

von Karsten K. (karsten42)


Lesenswert?

Ahhhh, Sehr schlau!
Danke Karl Heinz für deine Hinweise. Tatsächlich habe ich übersehen das 
die MUX Kanalauswahl nicht binär ist!

Schade das man per Mail kein Bier schicken kann sonst wäre jetzt eins 
unterwegs!

Daaaanke nochmals!

Gruß
Karsten

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.