AVR ADC Einsteigerproblem

OP #3518318
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
    }
#3518340
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
Gast #3518341
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
OP #3518355
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
            }
#3518375
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;
OP #3519133
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
  }

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