Forum: Mikrocontroller und Digitale Elektronik ADC-Messung ATmega64M1


von Lukas D. (lukdi)


Lesenswert?

Hallo zusammen,

ich habe einen ATmega64M1 und möchte mit diesem eine ADC-Messung 
durchführen. Ich arbeite mit einem externen 16MHz-Quarz. Habe hierfür 
auch die Fuse-Bits richtig eingestellt.

Mein Problem ist, dass ich eine 10-Bit-ADC habe (laut Datenblatt), 
jedoch werden im Register mehr als 10 Bit beschrieben (Ausgelesen mit 
dem Befehl ergebnis = ADCW).

Soll heißen, die Umrechnungsformel für 10 Bit (Vin = Vref*ADC/1024) nach 
Datenblatt liefert ein falsches Ergebnis, rechne ich jedoch mit 16 Bit 
(Vin = Vref*ADC/65535) funktioniert der Aufbau wie er soll!

Kann mir bitte jemand erklären was da los ist? Habe ich evtl. doch einen 
16-Bit ADC Wandler aber hab irgendwas darüber überlesen?


Das Programm:


#include "avr/io.h"
#include "avr/interrupt.h"



float dummy;
unsigned int ergebnis;

// UNTERPROGRAMME

void init_timer0(void);
void ADC_Init(void);


//HAUPTPROGRAMM

int main(void)
{
  DDRD |= (1<<DDD7); // Pin D7 als Ausgang festlegen, alle anderen 
D-Pins sind als Input deklariert! S.72
  PORTD |= 0b0111111; //Pin D7 ausschalten, alle anderen D-Pins sind 
eingeschalten. Da diese als Input deklariert sind, wurde jetzt 
Pull-Up-Resistor aktiviert

  init_timer0();  // Timer0 aufrufen
  ADC_Init();    // Aufrufen des Unterprogramms ADC-Initialisierung

  ergebnis=0;
  dummy = 0;

  sei();

  while(1)
  {/* PROGRAMMSCHLEIFE*/}

  return(0);
}


//UNTERPROGRAMME

//#Timer_Einstellungen

void init_timer0(void)
{
  TCNT0 = 0; // Timer/Counter resetet
  OCR0A = 127; // nach 128 Stufen zurück auf
  TIMSK0 = (1<<OCIE0A); // compare match A interrupt is enabled
  TCCR0A |= (1<<COM0A1)|(0<<COM0A0)|(1<<WGM01); // Clear OC0A on compare 
match
  TIFR0 = (1<<OCF0A); // Führe Match-Interrupt aus!
  TCCR0B |= (1<<CS02)|(0<<CS01)|(1<<CS00); // clock prescaler auf /1024
}


// ADC_Initialisieren

void ADC_Init(void)
{
  ADMUX = (1<<AREFEN) | (0<<ISRCEN) | (0<<REFS1) | (1<<REFS0);    // 
externe Referenzspannung 5V (Versorgungsspannung)
  ADMUX |= (0<<MUX4)|(0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(1<<MUX0); // ADC5

  ADCSRA |= (1<<ADEN);  // Enable ADC
  ADCSRA |= (1<<ADSC);  // In Free-Running mode this bit to 1 for first 
conversion
  ADCSRA |= (1<<ADATE); // ADC auto trigger enable
  ADCSRA |= (1<<ADIE);  // Enable Interrupt
  ADCSRA |= (0<<ADLAR);
  ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);  // /128 prescale

  ADCSRB = (0<<ADTS3) | (0<<ADTS2) | (1<<ADTS1) | (0<<ADTS0);  // 
Triggersource Timer/counter0 compare match A
  ADCSRB = (1<<ADHSM);  // ADC-High Speed Mode

  DIDR0 = (1<<ADC0D); // digital input disabled

}


//ISR's

ISR(ADC_vect)
{

  ergebnis = ADCW;
  dummy = (4.96)*ergebnis/65535;  //Vin = Vref*ADC/1024

  if (dummy>=1.8)
  {
    PORTD = (1<<DDD7); //PD7 anschalten
  }

  else
  {
    PORTD = 0x00;
  }
}

von Ralf G. (ralg)


Lesenswert?

Du hast das Ergebnis der Wandlung links ausgerichtet (für 8-Bit-Ergebnis 
gedacht).

...

...

Sieh dir mal ADLAR und AREFEN genauer an.

von Toni R. (torei55)


Lesenswert?

und irgendwie Schmeißt Du die Register durcheinander.
Mal abgesehen von der 0 Schieberei (0 << XXX)

von Lukas D. (lukdi)


Lesenswert?

Habe die Erläuterung im Datenblatt AREFEN falsch verstanden! Jetzt geht 
es wie es soll!
Danke für die schnelle Hilfestellung!

von Ralf G. (ralg)


Lesenswert?

Lukas D. schrieb:
> Jetzt geht es wie es soll!

Reiner Zufall!

Du hast die Zuordnung der Bits zu den Registern vertauscht!

von Lukas D. (lukdi)


Angehängte Dateien:

Lesenswert?

Hallo nochmal! Ich habe mir das ganze jetzt moch einmal angesehen und 
verstehe es nicht!

Ich habe doch das Ergebnis der Wandlung rechts ausgerichtet (10 Bit). 
Siehe dazu Bild ADLAR und ADLAR1. Wenn ich ADLAR=0 "setze" (lasse wie er 
ist) habe ich das Register rechts ausgerichtet und 10 Bit.

Wie/wo sind die Register durcheinander geraten?

Zudem würde mich interessieren wie das mit dem Register generell ist. 
Wenn ADLAR=0 wird zuerst ADCL und dann ADCH beschrieben, richtig? Das 
Auslesen habe ich so verstanden: Zuerst ADCL und erst dann ADCH 
auslesen. Aber das geschieht im Background. Da habe ich ja nichts drann 
geändert!


Was auch nicht ganz durchsichtig ist, ist die Einstellung zur externen 
Referenzspannung!

Hier habe ich die zweite Einstellung von oben gewählt, siehe Bild 
AREFEN! Somit muss AREFEN=1 gesetzt werden. Etwas weiter unten im 
Datenblatt finde ich aber folgende Info zu AREFEN, Bild AREFEN1. Das 
wiederspricht sich doch!!! AREFEN=0 damit interne AREF getrennt ist von 
AREF. Oben steht aber das AREFEN=1 gesetzt werden soll um externen 
Kondensator auf AREF zu legen.

Generell interessiert mich auch wo die Unterschiede in den ersten drei 
Einstellungsoptionen zur Referenzspannung liegen?

1: External Vref on AREF pin, Internal Vref is switched off
2: AVcc with external capacitor connected on the AREF pin
3: AVcc (no external capacitor connected on the AREF pin)

1 und 3 scheinen das selbe zu sein?!

Wenn Ihr mir das Entwirren könntet wäre ich euch sehr dankbar!

Grüße,

Luk

von S. Landolt (Gast)


Lesenswert?

> ADMUX = (1<<AREFEN) | (0<<ISRCEN) | (0<<REFS1) | (1<<REFS0);
ISRCEN steht in ADCSRB (auch wenn das hier wegen der 0 keine Rolle 
spielt)
AREFEN dito, spielt eine Rolle.

> 1 und 3 scheinen das selbe zu sein?!
Mitnichten. Bei 1 muss eine Referenzspannung von außen angelegt werden, 
bei 3 wird die Versorgungsspannung AVcc als Referenz benutzt.

von Ralf G. (ralg)


Lesenswert?

Das Bit ADLAR repräsentiert zur besseren Unterscheidung die Zahl 5. Mit 
'1 << ADLAR' kan man in irgendeinem Register das 5. Bit setzen. 
Genauso ist es mit 'AREFEN'.

Dein Eingangspost:
1
ADMUX = (1<<AREFEN)  /* .... */
2
//
3
//
4
ADCSRA |= (0<<ADLAR);
Diese beiden Befehle 'bearbeiten' in den jeweiligen Registern das 5.Bit.
Nur:
Das 5.Bit in ADMUX hat die Bezeichnung 'ADLAR'. Auch wenn du die 
Bezeichnung 'AREFEN' verwendest, sagst du dem µC trotzdem, das er das 
Ergebnis der Wandlung links ausrichten soll.
Beim zweiten Befehl passiert nichts Schlimmes. Nämlich gar nichts. Das 
wäre nur kritisch wenn 'ADATE' nicht gesetzt werden soll, und du mit '1 
<< ADLAR' das 5.Bit einschaltest. Bit 5 in 'ADCSRA'? Richtig 'ADATE'.
Die Auswahl der Referenz kann im Register 'ADCSRB' vorgenommen werden, 
in dem sich auch ein Bit (Nummer 5) befindet ... mit dem Namen 'AREFEN' 
...

Alle anderen Bits schaust du dir noch mal an.

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.