Atmega168 und ADC -> so richtig ?

#2814237
Lesenswert?

Hallo !

Ich möchte vom PINC4 (ADC4) ein analoges Signal eines Sensors abfragen.

Da ich in meinem Programm keine Warteschleifen gebrauchen kann, habe ich 
mich für den "Free Running"-Modus entschieden.
Und die positive Betriebsspannung als Referenz, da das Ganze mit 
Batterien betrieben werden soll.

Ist der "Programmfetzen" so richtig?
Muss ich noch Hardwaremäßig noch etwas beschalten, ausser Sensorsignal 
an PIN C4? (mal abgesehen von allem was nötig ist um den Controller 
laufen zu lassen)
1
...
2
uint16_t adc_result;
3

4
  ADMUX |= (1<<REFS0);         //AVCC Referenzspannung
5
  ADMUX |= (1<<ADLAR);         //ADC Left Adjust Result
6
  ADMUX |= (1<<MUX2);          //ADC4, PIN C4
7

8
  ADCSRA |= (1<<ADSC);                // Auto Trigger, Start Conversion
9
  ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);   // Frequenzvorteiler 128
10
  ADCSRA |= (1<<ADEN);                // ADC aktivieren
11

12
...
13

14
adc_result = ADCH;
15

16
...

Schon mal Danke für Eure Antworten !!!!
Gast #2814253
Lesenswert?

Hi

>Da ich in meinem Programm keine Warteschleifen gebrauchen kann, habe ich
>mich für den "Free Running"-Modus entschieden.

Dazu muss man den Free Running MOde auch einschalten:  ADATE in ADCSRA: 
ADC Auto Trigger Enable.

Wenn du nicht warten willst, dann lies den ADC-Wert im 
AD-Complete-Interrupt aus.

MfG Spess
#2814270
Lesenswert?

Hi, Spess !

Also dann so:
1
  ADMUX |= (1<<REFS0);         //AVCC Referenzspannung
2
  ADMUX |= (1<<ADLAR);         //ADC Left Adjust Result
3
  ADMUX |= (1<<MUX2);          //ADC4, PIN C4
4
  
5
  ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);   // Frequenzvorteiler 128
6
  ADCSRA |= (1<<ADEN);                // ADC aktivieren
7
  ADCSRA |= (1<<ADATE) | (1<<ADSC);          // Auto Trigger, Start Conversion


Warten ist jetzt relativ, ich kann im Programmablauf keine 
Zeitvertrödelung gebrauchen; also warten auf ein Ergebnis ist nicht 
möglich.
Gast #2814282
Lesenswert?

Aber warten du musst, kleiner Jedi....

Die erste Umwandlung braucht erstmal længer als die folgenden und die 
brauchen dann auch ein paar ADC-Takt-Zyklen (steht im Datenblatt).
Jetzt kannst du entweder auf das "ADC-Data-Ready"-Flag pollen oder einen 
Interrupt ausløsen lassen der dir deinen gespeicherten ADC-Wert 
aktualisiert.
#2814302
Lesenswert?

Also habe ich die Wahl, einfach die "Verzögerung" der ersten Messung zu 
akzeptieren oder nach der Initialisierung

while (ADCSRA & (1 << ADSC));

abzuwarten.

Aber nichts desto trotz, kann ich doch in meiner Programmschleife den 
Messwert abfragen und müsste doch bei "Free Running" einfach den zuletzt 
gemessenen Wert erhalten. Oder liege ich jetzt da falsch ?
1
....
2
while(1)
3
{
4
...
5
adc_result = ADCH;
6
...
7
}
#2814781
Lesenswert?

Sven W. schrieb:
> Also habe ich die Wahl, einfach die "Verzögerung" der ersten Messung zu
> akzeptieren oder nach der Initialisierung
>
> while (ADCSRA & (1 << ADSC));
>
> abzuwarten.
>

Man kann die Dinge aber auch umdrehen.
Sagt ja kein Mensch, dass man in der Zeit, in der der ADC arbeitet nicht 
etwas anderes tun darf.


Man kanns ja auch so machen
1
  ....
2
  while(1)
3
  {
4
    ...
5
    if( ADC ist fertig )
6
    {
7
      Messwert vom ADC holen
8
      Neue Messung am ADC anstossen
9

10
      Messwert verarbeiten
11
      ....
12
    }
13

14
    ...
15
  }

je nachdem, wieviel in den ... Phasen zu tun ist, kann man auch auf die 
if Abfrage komplett verzichten, weil man ja weiß, wieviele Takte der ADC 
für eine Wandlung benötigt. Benötigen alle Prgrammteile vom Starten des 
ADC bis zum Holen des Ergbnisses mehr Takte, dann ist sichergestellt, 
dass der ADC tatsächlich zu diesem Zeitpunkt fertig ist. Allerdings 
schadet der if wahrscheinlich auch nicht wirklich der Laufzeit.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren