Forum: Mikrocontroller und Digitale Elektronik ATMega8 interner ADC


von Tomato (Gast)


Lesenswert?

Hallo alle miteinander!

Ich möchte mit meinem ATMega8 Spannungen einlesen und diese dann mittels 
LED Anzeige ausgeben lassen (also bitweise Darstellung).

Hier ist schonmal mein Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
volatile uint16_t c = 0;
5
6
void out (volatile uint16_t value);
7
8
int main(void)
9
{
10
  DDRB |= (1 << PB0);
11
  DDRC |= 0x3E;
12
  DDRD |= 0xF0;
13
  
14
  ADMUX = 0x0000;
15
  ADCSRA |= (1<<ADFR) | (1<<ADEN) |  (1<<ADPS2);  
16
  ADCSRA |= (1<<ADIE);              
17
  sei();
18
  
19
  ADCSRA |= (1<<ADSC);              
20
  while (ADCSRA & (1<<ADSC))            
21
  {
22
  }
23
  
24
    while (1) 
25
    {
26
    ADCSRA |= (1<<ADSC);
27
    
28
    while (ADCSRA & (1<<ADSC))
29
    {
30
    }
31
32
    c = ADCL;
33
    c += (ADCH << 8);
34
    }
35
  
36
}
37
38
ISR (ADC_vect)
39
 {
40
    out(c);
41
  PORTB |= (1<<PB1);  //Zur Kontrolle, ob er ins ISR geht
42
  ADCSRA |= (1<<ADSC);
43
 }
44
45
void out (volatile uint16_t value)
46
{
47
  PORTB ^= (1<<PB0);
48
  PORTD &= ~0xF0;
49
  PORTC &= ~0x3E;
50
  
51
  PORTD |= (uint8_t)((value >> 2) & 0xF0);
52
  PORTC |= (uint8_t)(value & 0x3E);  
53
}

Das ganze will jetzt aber leider nicht so wie ich will. Anscheinend geht 
er nicht ins ISR, da die Kontroll LED nie angesprochen wird.
Liegt das jetzt an meiner Konfiguration? Obwohl da ja nur angeprochen 
wird, oder ist etwas mit meiner Ausgabe nicht in Ordnung?

Für Hilfe wäre ich sehr dankbar :)

von Dyson (Gast)


Lesenswert?

B1 ist nicht als Ausgang konfiguriert.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Tomato schrieb:
> Anscheinend geht er nicht ins ISR
Wofür brauchst du für diese simple Aufgabe einen Interrupt?
Ich würde die erst mal mit Polling lösen. Und ich sehe grade, dass du 
das auch tust. Zusätzlich zum Interupt...

Was passiert denn, wenn du das machst:
1
:
2
:
3
    ADCSRA |= (1<<ADSC);
4
    while (ADCSRA & (1<<ADSC))
5
    {
6
    }
7
    PORTB |= (1<<PB1);  //Zur Kontrolle, ob er überhaupt mal fertig wird
8
9
    while (1) 
10
:
11
:
12
ISR (ADC_vect)
13
{
14
   out(c);
15
//   PORTB |= (1<<PB1);  //Zur Kontrolle, ob er ins ISR geht
16
   ADCSRA |= (1<<ADSC);
17
}
18
:
19
:

BTW: dir ist schon klar, dass du den ADC nicht unbedingt selber in 2 
Zugriffen auslesen musst. Das macht der Compiler schon richtig, wenn du 
schreibst c = ADC;

von Tomato (Gast)


Lesenswert?

Oh nein ... so ein dummer Fehler ... Danke ^^
Jetzt weiß ich zumindest schonmal, dass er ins ISR reingeht.
Aber meine Ausgabe ist leider noch immer nicht ganz korrekt. Es leuchten 
permanent alle LEDs, obwohl ja nur die einzelnen Bits leuchten sollten.

Lothar M. schrieb:
> Was passiert denn, wenn du das machst:

Die Kontoll-LED leuchtet nicht

von HildeK (Gast)


Lesenswert?

Tomato schrieb:
> c = ADCL;
> c += (ADCH << 8);

Kleiner Tipp, das geht auch einfacher:
 c = ADCW;
oder
 c = ADC;

Zu deinem Problem:
schreib in der ADC-ISR
 PORTB |= (1<<PB0);  //Zur Kontrolle, ob er ins ISR geht
dann schaltet es auch den richtigen Pin :-)
PB0 statt PB1!

von S. Landolt (Gast)


Lesenswert?

Welche Spannung liegt an ADC0, welche an AREF?

von S. Landolt (Gast)


Lesenswert?

Wozu wird eigentlich ADFR gesetzt, wenn ohnehin jede Messung mit ADSC 
gestartet wird?

von Tomato (Gast)


Lesenswert?

Ich habe meinen Fehler gefunden.
Ich dachte, da ich meine "unbekannte" Spannung einlese benötige ich kein 
AREF. Das war aber eine falsche Annahme ^^'

Vielen Dank für die Antworten.
Solche Schusselfehler sollten jetzt nicht mehr vorkommen.

von HildeK (Gast)


Lesenswert?

Wozu verwendest du hier den ADC-Interrupt?
Nach meinem bisherigen Verständnis ist der hauptsächlich dann sinnvoll, 
wenn man mit SLEEP_MODE_ADC den Noise Reduction Mode des ADC verwenden 
oder parallel zur AD-Wandlung was anderes tun will. Beides sehe ich in 
deinem Code nicht.
Vielleicht fehlt mir aber auch ein wenig Wissen über weitere Optionen.

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.