Forum: Mikrocontroller und Digitale Elektronik ADCW Register Atmega8


von Michael (Gast)


Lesenswert?

Hallo Leute,

ich möchte gerne zwei Spannungswerte durchgängig mit Hilfe des 
AD-Wandlers des Atmega8 ausgeben.
Mit einem Wert habe ich das auch so weit hinbekommen:

// Interrupt-Routine:
... unsigned int result1 = ADCW;
// Hierfür lese ich Kanal 4 ein:
... ADMUX = (1<<REFS0) | 4;

Nun möchte ich einen weiteren Kanal einlesen.
Aber den Wert kann ich ja nicht im ADCW Register speichern...
Im Datenblatt des Atmega steht leider nichts über das ADCW Register.

Hat jemand vielleicht eine Idee, wie ich das lösen kann?

Vielen Dank und Gruß

Micha

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Michael schrieb:

> Aber den Wert kann ich ja nicht im ADCW Register speichern...

Aus diesem Register liest du ihn ja auch nur aus.  Speichern
musst du ihn in einer zweiten Variablen, also irgendwas anderes
als "result1".

> Im Datenblatt des Atmega steht leider nichts über das ADCW Register.

Der Name ADCW ist nur ein Pseudonym für die Vereinigung von ADCL und
ADCH.  Normalerweise werden die Namen derartiger 16-bit-Pseudoregister
einfach durch Weglassen von H bzw. L gebildet, aber da der sich hier
ergebende Name ADC zugleich eine Assemblermnemonik ist (für "add with
carry"), gibt es zusätzlich noch den Namen ADCW als Alias dafür,
wobei bei der Benutzung von <avr/io.h> in einer Assemblerdatei nur
dieser Name benutzbar ist.

von Michael (Gast)


Lesenswert?

Danke für die Antwort, Jörg.

Jörg Wunsch schrieb:
> Aus diesem Register liest du ihn ja auch nur aus.  Speichern
> musst du ihn in einer zweiten Variablen, also irgendwas anderes
> als "result1".

Wenn ich also eine zweite Variable definiere, kann ich die dann 
ebenfalls aus dem Register ADCW auslesen?

z.B.:
unsigned int result2 = ADCW;

Dementsprechend muss ich in main-file folgendes hinzufügen:
ADMUX = (1<<REFS0) | 3;
also einen anderen Kanal einlesen.

Ist das so richtig?

Kann ich dann gleichzeitig in der Interrupt Routine auf beide Werte 
zugreifen?

von Karl H. (kbuchegg)


Lesenswert?

Michael schrieb:

> Ist das so richtig?

Im wesentlichen: Ja
Auch wenn ich mir nicht sicher bin, ob du das richtige meinst.

>
> Kann ich dann gleichzeitig in der Interrupt Routine auf beide Werte
> zugreifen?

Nein.
Du hast im µC nur einen ADC. Dessen Eingang kannst du auf verschiedene 
Eingangspins schalten lassen und so unterschiedliche Eingänge messen 
lassen. Aber nur hintereinander! Denn ... es existiert nur 1 Analog 
Digital Konverter.

Den Interrupt bekommst du, nachdem der ADC fertig gewandelt hat. Also 
nach einer Messung. Daher kannst du dort nicht 2 Eingänge abfragen, denn 
der andere Eingang wurde ja noch gar nicht vermessen.


Darf ich fragen, warum du da überhaupt Interrupts benutzt?
Mir scheint deine C-Kentnisse sind noch nicht so weit, dass ich dir eine 
saubere und korrekte Behandlung von Interrupts zutrauen würde.

im AVR-GCC-Tutorial, im Abschnitt über den ADC gibt es fix fertige 
Routinen, die du nur benutzen musst. Und ich denke (ohne jetzt deine 
Anwendung zu kennen), dass du damit erst mal besser bedient wärst.

von Michael (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Darf ich fragen, warum du da überhaupt Interrupts benutzt?

Ich benutze ein Interrupt nach abgeschlossener AD-Wandlung.
Den Messwert lese ich aus dem ADCW Register aus, um damit weiter 
arbeiten zu können. (s.oben)
Dies könnte ich aber auch in der main-Datei aufrufen.

Mir ist nur wichtig, dass ich dann in der main-Datei folgendes aufrufen 
kann:

int main()
{
  uint16_t result1;
  uint16_t result2;
  ADC_Init();

  while( 1 ) {
    result1 = ADC_Read(3);  // Kanal 3
    // mach was mit result1

    result2 = ADC_Read(4);  // Kanal 4
    // mach was mit result2
  }
}

Die Interrupts möchte ich verwenden, damit ich jeweils die aktuellen 
Werte für result1 und result2 erhalte.
Werden diese Werte in der main-Datei denn aktualisiert oder nur einmal 
ausgelesen und dann gespeichert?

Vielen Dank

von Karl H. (kbuchegg)


Lesenswert?

Michael schrieb:
> Karl Heinz Buchegger schrieb:
>> Darf ich fragen, warum du da überhaupt Interrupts benutzt?
>
> Ich benutze ein Interrupt nach abgeschlossener AD-Wandlung.
> Den Messwert lese ich aus dem ADCW Register aus, um damit weiter
> arbeiten zu können. (s.oben)

Das ist nicht die Frage.
Die Frage war: WARUM Interrupts.
Warum nicht einfach ganz normal pollen.


> int main()
> {
>   uint16_t result1;
>   uint16_t result2;
>   ADC_Init();
>
>   while( 1 ) {
>     result1 = ADC_Read(3);  // Kanal 3
>     // mach was mit result1
>
>     result2 = ADC_Read(4);  // Kanal 4
>     // mach was mit result2
>   }
> }
>
> Die Interrupts möchte ich verwenden, damit ich jeweils die aktuellen
> Werte für result1 und result2 erhalte.

Die hast du sowieso.
In dem Moment, in dem du ADC_Read aufrufst, wird der angegebene Kanal 
gemessen.

> Werden diese Werte in der main-Datei denn aktualisiert oder nur einmal
> ausgelesen und dann gespeichert?

Bei jedem Aufruf von ADC_Read findet eine Messung statt. Und zwar am 
angegebenen Kanal.

Das ist nichts anderes als

    i = PINB;

das wird auch jedesmal ausgeführt und der zum Zeitpunkt der Ausführung 
aktuelle Zustand der Portpins an i zugewiesen. Die ADC Funktionen sind 
so geschrieben, dass sie sich genau gleich verhalten. Davon kann man 
sich durch Studium der ADC_Read Funktionen aus dem Tut leicht 
überzeugen. Bei jedem Aufruf wird eine Messung angestossen und dessen 
Beendigung abgewartet.

von Michael (Gast)


Lesenswert?

Danke Karl, hast mir schon sehr weiter geholfen.

> Die Frage war: WARUM Interrupts.
> Warum nicht einfach ganz normal pollen.

Damit ich eine kontinuierliche Messung, bzw. einen aktuellen Messwert 
erhalte, wollte ich einen interrupt verwenden.


> Bei jedem Aufruf von ADC_Read findet eine Messung statt. Und zwar am
> angegebenen Kanal.

Der zu messende Wert in meiner Applikation ändert sich jedoch und muss 
ständig gemessen werden.
Die Messung durch ADC_Read findet doch aber nur einmal statt oder sehe 
ich das falsch?

von Karl H. (kbuchegg)


Lesenswert?

Michael schrieb:
> Danke Karl, hast mir schon sehr weiter geholfen.
>
>> Die Frage war: WARUM Interrupts.
>> Warum nicht einfach ganz normal pollen.
>
> Damit ich eine kontinuierliche Messung, bzw. einen aktuellen Messwert
> erhalte, wollte ich einen interrupt verwenden.
>
>
>> Bei jedem Aufruf von ADC_Read findet eine Messung statt. Und zwar am
>> angegebenen Kanal.
>
> Der zu messende Wert in meiner Applikation ändert sich jedoch und muss
> ständig gemessen werden.
> Die Messung durch ADC_Read findet doch aber nur einmal statt oder sehe
> ich das falsch?

Welchen Teil des Satzes

Bei jedem Aufruf von ADC_Read findet eine Messung statt.

verstehst du nicht?

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.