Forum: Mikrocontroller und Digitale Elektronik Atmega644 - ADC Problem


von Rainer B. (guitero)


Lesenswert?

Hallo zusammen,

baue gerade meine erste eigene Schaltung mit einem Atmega644.
Die Grundbeschaltung habe ich so aufgebaut:
http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC

Ich möchte über den ADC 12 verschiedene Taster einlesen. Dazu habe ich 
die Tastenmatrix genommen wie sie von Peter Dannegger hier vorgestellt 
wurde:
Beitrag "Tastenmatrix auslesen über nur 2 Leitungen"

Als Eingang benutzte ich den ADC0 (PINA0) des uC. Testweise liegen über 
die Tastenmatrix feste 1,2 V an ADC0 an, den Wert habe ich
auch entsprechend nachgemessen.

Die Initialisierung des ADC sieht so aus:
1
void adc_init(void)
2
{
3
  ADCSRA = (1<<ADPS2)|  (0<<ADPS1) | (1<<ADPS0);    
4
  ADCSRA |= (1<<ADEN);          
5
  ADMUX = 1<<REFS1 | 1<<REFS0;    
6
  ADMUX = 0<<MUX4 | 0<<MUX3 |0<<MUX2 | 0<<MUX1 | 0<<MUX0;  
7
  ADMUX |=(1<<ADLAR);            
8
  ADCSRA |= (1<<ADSC);        
9
  ADCSRB = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0); 
10
}


Die Funktion zum Auslesen sollte korrekt sein, da ich die schon häufiger 
verwendet habe.
In AVR Studio ist AVREF auf 5V gesetzt. VTARGET wird mit 5.2 Volt 
angezeigt.

Das eigentliche Problem ist, dass ich immer einen Wert von 255 empfange, 
egal was ich an den ADC0 anlege. Auch wenn ich den PIN freilasse
bekomme ich diesen Wert. Der ADC läuft im Free Running Modus.
Habe ich irgendetwas grundlegendes übersehen?

Wäre dankbar wenn mir jemand einen Tipp geben könnte. Habe keine Ahnung 
mehr was ich noch ausprobieren kann.

Danke schonmal!

Gruß, guitero

von spess53 (Gast)


Lesenswert?

Hi

>Der ADC läuft im Free Running Modus.

Nein.

>Habe ich irgendetwas grundlegendes übersehen?

Ja. Für Free Running muss ADATE in ADCSRA gesetzt werden.

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

Noch etwas:

ADMUX = 1<<REFS1 | 1<<REFS0;

ist:

Internal 2.56V Voltage Reference with external capacitor at AREF pin.

>In AVR Studio ist AVREF auf 5V gesetzt.

Du hast hoffentlich den AREF-Jumper entfernt.

MfG Spess

von Hubert G. (hubertg)


Lesenswert?

Wenn ich dieses ADC-init im Simulator laufen lasse, dann kommt nach 
diesen Zeilen:
ADMUX = 1<<REFS1 | 1<<REFS0;
ADMUX = 0<<MUX4 | 0<<MUX3 |0<<MUX2 | 0<<MUX1 | 0<<MUX0;

Intern Vref turned off
Vielleicht solltest du die zweite ADMUX Zeile mal überdenken.

von spess53 (Gast)


Lesenswert?

Hi

>ADMUX = 1<<REFS1 | 1<<REFS0;
>ADMUX = 0<<MUX4 | 0<<MUX3 |0<<MUX2 | 0<<MUX1 | 0<<MUX0;

>Intern Vref turned off
>Vielleicht solltest du die zweite ADMUX Zeile mal überdenken.

Dann stimmt es aber mit der externen Refernzspannung. Also ignoriere 
meinen zweiten Beitrag und kontrolliere jetzt ob der AREF-Jumper 
gesteckt ist.

MfG Spess

von Rainer B. (guitero)


Lesenswert?

Danke erstmal für die schnelle Anwort.

Habe das ADATE Bit nun gesetzt, aber jetzt kommt leider gar nichts mehr 
an.

spess53 schrieb:
> Du hast hoffentlich den AREF-Jumper entfernt.

Welchen Jumper meinst du? Ich benutze kein STK500, sondern bin dabei mir 
eine eigene Schaltung zu bauen. Zum Programmieren benutze ich einen 
ISP-Programmer.
Habe AREF im AVR Studio auf 5V gesetzt und möchte mit der internen 
Referenz arbeiten.

Ich begebe mich wieder auf Fehlersuche.

Gruß,
guitero

von Hubert G. (hubertg)


Lesenswert?

Das AREF im AVR-Studio bewirkt in deiner Schaltung nichts.
Du hast auf Ext.Referenz gestellt und somit keine Spannung an AREF.

von Rainer B. (guitero)


Lesenswert?

Hallo nochmal,

@HubertG.: hatte deinen Beitrag ganz übersehen.

Hubert G. schrieb:
> Intern Vref turned off
> Vielleicht solltest du die zweite ADMUX Zeile mal überdenken.

Verstehe ich nicht!?
Mit ADMUX = 1<<REFS1 | 1<<REFS0 setze ich die interene Referenz und mit 
MUX4..0 wähle ich den PORT-Pin aus. Und den habe ich doch auf 0 stehen 
lassen, also PA0. Wo liegt der Fehler?

Hubert G. schrieb:
> Du hast auf Ext.Referenz gestellt und somit keine Spannung an AREF.
Laut Datenblatt habe ich doch die interne Referenz in Betrieb. Habe ich 
das falsche Datenblatt?

guitero

von spess53 (Gast)


Lesenswert?

Hi

>Wo liegt der Fehler?

Am fehlenden '|='.

MfG Spess

von Hubert G. (hubertg)


Lesenswert?

ADMUX = 0<<MUX4 | 0<<MUX3 |0<<MUX2 | 0<<MUX1 | 0<<MUX0;
Lass mal diese Zeile weg.

von Rainer B. (guitero)


Lesenswert?

Hallo,

spess53 schrieb:
> Am fehlenden '|='.

Tut mir Leid, aber ich kann dir nicht folgen.
Ich möchte beide Pins auf 1 setzen, das mache ich doch folgendermaßen:
1
ADMUX = (1<<REFS1) | (1<<REFS0);
Wozu dann das '|='. Das benutze ich doch nur, wenn ich nur EINEN Pin 
verODERn möchte, oder nicht?

Hubert G. schrieb:
> ADMUX = 0<<MUX4 | 0<<MUX3 |0<<MUX2 | 0<<MUX1 | 0<<MUX0;

Ich weiß das die Zeile im Grunde überflüssig ist, aber warum ist sie 
falsch.
Ich habe das Gefühl ich komme nicht dahinter, was ihr mir sagen wollt...

von spess53 (Gast)


Lesenswert?

Hi

>Ich weiß das die Zeile im Grunde überflüssig ist, aber warum ist sie
>falsch.

Weil du die in

ADMUX = (1<<REFS1) | (1<<REFS0);

gemachten Einstellungen gnadenlos überschreibst. Mach es so wie bei den 
anderen Registern.

MfG Spess

von Steffen (Gast)


Lesenswert?

Mit der Zeile setzt du ADMUX aber wieder auf Null, weil du alles 
vorherige überschreibst. Mit |= funktioniert es, wenn du die Zeile (die 
überflüssig ist) weglässt, funktioniert es auch!

von Rainer B. (guitero)


Lesenswert?

Vielen Dank an euch! Die Mühle läuft.

Gruß,
guitero

von Rainer B. (guitero)


Lesenswert?

Hallo nochmal,

ich habe einige Probleme den Quellcode von Peter Dannegger zu verstehen:

Beitrag "Tastenmatrix auslesen über nur 2 Leitungen"

Am besten fange ich mal vorne an:
1
static inline
2
u16 key_no( u8 adcval )
3
{
4
  u16 num = 0x1000;      //4096 dezimal
5
  prog_uint8_t * thr = THRESHOLDS;  //hier werden alle Schwellwerte gespeichert
6
7
  while( adcval < pgm_read_byte( thr ))
8
  {
9
    thr++;
10
    num >>= 1;
11
  }
12
  return num & ~0x1000;
13
}

Hier wird die aktuelle Tastennummer ermittelt durch Übergabe des 
eingelesenen ADC-Wertes. Innerhalb der while-Schleife wird dann der 
ADC-Wert mit der Treshold-Liste verglichen. Soweit hab ich das 
verstanden. Aber was kommt am Ende dabei raus? Was bedeutet
1
num >>= 1;

und was wird hier zurückgegeben?
1
return num & ~0x1000;

Diese Zeilen innerhalb der main-Schleife verstehe ich auch nicht.
Wozu werden die Bits hier nach links geschiftet und wie kommt man auf 
"8", "4" oder "0".
1
  PORTA = 0xFF;
2
  DDRA = 0xFF;
3
  for(;;){
4
    if( get_key_press( 1<<8 ))    // "1"
5
      PORTA ^= 1<<0;      //  toggle
6
    if( get_key_press( 1<<4 ))    // "2"
7
      PORTA ^= 1<<1;
8
    if( get_key_press( 1<<0 ))    // "3"
9
      PORTA ^= 1<<2;

Das wären erstmal die wichtigsten Fragen. Wäre nett wenn mich dazu 
jemand aufklären könnte.

Gruß,
guitero

von Rainer B. (guitero)


Lesenswert?

Haben einen eigenen Thread dazu aufgemacht.

Beitrag "Problem mit C-Quellcode "Tastenmatrix einlesen""

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.