Forum: Mikrocontroller und Digitale Elektronik AVR ADC Einsteigerproblem


von Mike L. (mikelee)


Lesenswert?

Hallo,

ich setzte mich seit mehreren Tagen mit dem ADC des ATTiny261a 
auseinander und sehe den Fehler den ich mache nicht. Das Datenblatt und 
die Tutorials/Foren konnten mir nicht weiter helfen, deshalb hoffe ich 
jetzt auf eure Hilfe.

Mein Ziel ist es die Werte des ADCH Registers auf den 7 LEDs am PORTB 
anzuzeigen. Dabei sollen sich LEDs in Abhängigkeit des Trimmers ein bzw. 
ausschalten.

Ich habe Lösungen aus verschiedenen Tutorials probiert und bin zu keinem 
Ergebniss gekommen. Es Leuchten entweder alle LEDs, keine oder die 
LED0-LED2 dauerhaft (auch wenn ich am Trimmer drehe oder sogar die 
Verbindung zum Pin des ADC2 trenne).

Mein letzter Versuch besteht aus den Informationen die mir das 
Datenblatt liefert.

Den Quellcode habe ich nach meinem Verständnis kommentiert, ich würde 
mich freuen wenn ihr mich korrigiert wenn etwas nicht stimmt.

Sind da Fehler im Quellcode oder habe ich bereits in der Schaltung einen 
Fehler?

Danke schon mal.
1
        ++++++++++
2
        +        +          +----- GND
3
 LED0 --+PB0  PA2+-- TRIMMER(1kOhm)
4
        +        +          +----- VCC
5
 LED1 --+PB1     +  
6
        +
7
 LED2 --+PB2
8
        + 
9
 LED3 --+PB3
10
        +
11
 LED4 --+PB4
12
        +
13
 LED5 --+PB5
14
        +
15
 LED6 --+PB6
16
        +
17
        +++++++++
1
  
2
3
    #include <avr/io.h>
4
     
5
    int main(void)
6
    {
7
            // ADC einschalten
8
            ADCSRA |= (1<<ADEN);
9
            // Ergebnis linksbündig ADCH ADCL
10
            ADMUX |= (1<<ADLAR);
11
            // PORTA2 zum Messen verwenden
12
            ADMUX |= (1<<1);
13
            // Frequenz durch 8 Teilen für 125KHz
14
            ADCSRA |= (1<<ADPS0);
15
            ADCSRA |= (1<<ADPS1);
16
           
17
            while(1){      
18
                    // Muss vor jeder Messung auf high gesetzt werden beim Single Conversion Mode
19
                    ADCSRA |= (1<<ADSC);
20
                   
21
                    // Warten bis ADIF = 0 (Messung abgeschlossen)
22
                    while((ADCSRA &ADIF)==0){}
23
                   
24
                    //ADCH wird gelesen (Zugriff auf das ADCH und ADCL Register wird wieder freigeschaltet)
25
                    PORTB = ADCH;
26
                   
27
                    //Neuen Messvorgang starten
28
                    ADCSRA &= ~(1<<ADSC);
29
                    ADCSRA &= ~(1<<ADIF);
30
            }
31
    }

von San L. (zwillingsfreunde)


Lesenswert?

Zwar keinerlei Erfahrung mit dem ATTiny und auch sonst wirst du 
garantiert bessere hilfe kriegen als von mir.

Aber vielleicht hilft dir die Idee ja weiter:
Geh mal mit deinem Debugger Online und setz nach der messung einen 
Breakpoint. Danach lässt du dir mal anzeigen, was du in deinem ADCH 
Register hast. So kannst du einschränken, wo der Fehler sein könnte, 
denn so wirst du schnell erkennen ob der Wert im Register ca. deiner 
Eingangsspannung entspricht (Kannst du dir ja ausrechnen).

Mfg

von spess53 (Gast)


Lesenswert?

Hi

>ADCSRA &= ~(1<<ADIF);

Das Flag wird durch schreiben einer 1 gelöscht.

>while((ADCSRA &ADIF)==0){}

Warum fragst du nicht ADSC ab? Datenblatt:

ADSC will read as one as long as a conversion is in progress. When the 
conversion is complete, it returns to zero.

MfG Spess

von Mike L. (mikelee)


Lesenswert?

@San Lue
Debugger habe ich leider noch keinen.

@spess53
Das heißt dann, dass ich das ADIF ignorieren kann weil das ADSC auch 
über Fertigstellung informiert?
1
while(1){      
2
                    // Muss vor jeder Messung auf high gesetzt werden beim Single Conversion Mode
3
                    ADCSRA |= (1<<ADSC);              
4
                    // Warten bis ADIF = 0 (Messung abgeschlossen)
5
                    while((ADCSRA &ADIF)==1){}
6
                    //ADCH wird gelesen (Zugriff auf das ADCH und ADCL Register wird wieder freigeschaltet)
7
                    PORTB = ADCH;
8
            }

von spess53 (Gast)


Lesenswert?

Hi

>Das heißt dann, dass ich das ADIF ignorieren kann weil das ADSC auch
>über Fertigstellung informiert?

Ja.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Mike L. schrieb:

> Das heißt dann, dass ich das ADIF ignorieren kann weil das ADSC auch
> über Fertigstellung informiert?

Wie spess schon sagte: Ja

Und so
1
while((ADCSRA &ADIF)==0){}
schon gleich gar nicht.
Eine Bitabfrage würde sowieso anders aussehen.

Beide Änderungen in einem
1
      ADCSRA |= ( 1 << ADSC );
2
      while( ADCSRA & ( 1 << ADSC ) )
3
        ;
4
5
      PORTB = ADCH;

von Mike L. (mikelee)


Lesenswert?

Danke für eure Antworten, ich werde es heute Abend testen und 
Rückmeldung geben.

von Stefan D. (reverse)


Lesenswert?


von Mike L. (mikelee)


Lesenswert?

Es funktioniert jetzt wie gewünscht.
Danke für eure Hilfe!
1
#include <avr/io.h>
2
3
int main(void)
4
{
5
  DDRB = 0xFF;
6
  // ADC einschalten
7
    ADCSRA |= (1<<ADEN);
8
  // Ergebnis linksbündig ADCH ADCL
9
  ADMUX |= (1<<ADLAR);
10
  // PORTA2 zum Messen verwenden
11
  ADMUX |= (1<<1);
12
  // Frequenz durch 8 Teilen für 125KHz
13
  ADCSRA |= (1<<ADPS0);
14
  ADCSRA |= (1<<ADPS1);
15
  
16
  while(1){  
17
    // Muss vor jeder Messung auf high gesetzt werden beim Single Conversion Mode um die Messung zu starten
18
    ADCSRA |= (1<<ADSC);
19
    // Warten solange bis ADSC == 1 (Messung abgeschlossen) 
20
    while( ADCSRA & ( 1 << ADSC ) );    
21
    //ADCH wird gelesen (Zugriff auf das ADCH und ADCL Register wird wieder freigeschaltet)
22
    PORTB = ADCH;
23
  }

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.