Forum: Compiler & IDEs AD Wandlung mit MEGA 16


von Udo S. (Firma: allround) (1udo1)


Lesenswert?

Hallo,

ich möchte den Pegel an PA0 einlesen und dann an PORT C ansehen. An PA0 
ist ein 10 Kiloohm Poti angeschlossen.

Frage:

Ist da irgendetwas falsch in meinem Programm? Ich kann den Fehler nicht

finden. Die LEDs an PORT C bleiben dunkel, egal, wie ich das Poti

verstelle. Andere Programme laufen auf dem Board.

1
/* AD Wandler mit dem MEGA 16, PA0 ist Eingang, Ausgang PORT C */
2
3
/* An Port A0 ist ein 10 K Poti angeschlossen*/
4
5
/* Takt 12 MHZ, für AD geteilt durch 68, also 185 kHZ */
6
7
/* interne Referenz mit 2,56 V */
8
9
10
#define F_CPU 1200000 
11
12
#include <avr/io.h>
13
14
#define LED PORTC //  LED an PORTC
15
16
char adc()
17
18
{
19
  
20
  ADCSRA |= (1 << ADEN); // Analog-Digital enable bit
21
  
22
  
23
  ADCSRA |= (1 << ADSC);   
24
  
25
        while (ADCSRA & (1 << ADSC)); // warten, bis Wandlung fertig ist
26
  
27
  
28
  ADCSRA |= (1 << ADSC); // start single conversion
29
  
30
  while (ADCSRA & (1 << ADSC)) // warten, bis Wandlung fertig ist  
31
  
32
  ADCSRA &= ~(1<<ADEN); // ADC deaktivieren
33
  
34
  
35
  return ADCH;
36
  
37
}
38
39
40
int main(void)
41
42
{
43
  DDRC = 0xFF;  // PORTC Ausgang
44
  PORTC = 0xFF; // HIGH, LEDs dunkel
45
46
  // AD enable, prescaler 64 (187,5 KHz)
47
  ADCSRA |= (1 << ADEN) | (1 << ADPS1)  | (1 << ADPS2); 
48
49
        // AD0 an PA0
50
  // AD result store in (more significant bit in ADCH)
51
  // Referenz 2,56 V intern
52
  ADMUX |= (1 << REFS0) | (1 << REFS1) | (1 << ADLAR) |(1 << MUX0); 
53
  
54
  for (;;)
55
  
56
  {
57
    
58
    LED = adc(); // PORTD output, Auslesen des ADCH nach PORT C
59
    
60
  }
61
  
62
  return 0;
63
  
64
}

von Karl H. (kbuchegg)


Lesenswert?

>    ..... (1 << MUX0);

Sagtest du nicht, dein Poti hängt an PA0 ?

von Udo S. (Firma: allround) (1udo1)


Lesenswert?

Hallo Karl Heinz,

Danke!!! Ich habe mich mit MUX0 nach PA0 täuschen lassen. Diese "0" 
bringt die Nichtgeübten schon mal in Verlegenheit. Ich denke, das ist 
der Fehler. Ich muss alle MUX auf "0" belassen. Werde es sofort 
ausprobieren!

von Karl H. (kbuchegg)


Lesenswert?

Das mit den MUX Bits kann man sich ganz einfach merken. Vergiss die 
Bitnamen und sieh die 5 MUX-Bitstellen einfach als Binärzahl an. Die 
Binärzahl ist die Nummer des Kanals. Sind die 5 Stellen also eine binäre 
0, dann wandelt der ADC vom Kanal 0, welcher eben am PA0 hängt.
Sind diese 5 Bits eine binäre 1 (also 00001), dann hängt der ADC am PA1. 
Steht in den 5 Bits eine binäre 2, dann hängt der ADC an PA2, etc. etc.

D.h. im Grunde ist diese Schreibweise
1
  ADMUX |= (1 << REFS0) | (1 << REFS1) | (1 << ADLAR) | (Kanal & 0x1F);
besser, wobei Kanal dann einfach nur eine Zahl von 0 bis 31 ist. Eben 
genau die Kanalnummer, die der Tabelle im Datenblatt entspricht. Im 
Speziellen heisst das, dass zb mit einem Wert von zb 5 in Kanal, der ADC 
von PA5 wegwandelt. D.h. bei den wichtigen single ended Modi hast du 
eine direkte Entsprechung der Zahlen von 0 bis 7 zu den entsprechenden 
Pins am Port A.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> D.h. im Grunde ist diese Schreibweise
>
>   ADMUX |= (1 << REFS0) | (1 << REFS1) | (1 << ADLAR) | (Kanal & 0x1F);

und warum ein |= ?

Zudem liefert adc() ein char, welches üblicherweise signed ist.  Der 
Wert ist aber unsigned, also uint8_t.

von Karl H. (kbuchegg)


Lesenswert?

Johann L. schrieb:
> Karl Heinz Buchegger schrieb:
>> D.h. im Grunde ist diese Schreibweise
>>
>>   ADMUX |= (1 << REFS0) | (1 << REFS1) | (1 << ADLAR) | (Kanal & 0x1F);
>
> und warum ein |= ?
>
> Zudem liefert adc() ein char, welches üblicherweise signed ist.  Der
> Wert ist aber unsigned, also uint8_t.


Hast du recht.
Darauf hab ich jetzt überhaupt nicht geachtet und mich nur auf die 
Fragestellung konzentriert, warum der TO offenbar immer ein 0-Ergebnis 
ausliest.

von Udo S. (Firma: allround) (1udo1)


Lesenswert?

Wunderbar,es klappt.

Habe aber noch eine Frage zu folgender Zeile:

*while (ADCSRA & (1 << ADSC)) // warten, bis Wandlung fertig ist*


Mir sind die logischen Verknüpfungen bekannt, aber ich kann sie 
innerhalb

des Klammerausdrucks nicht interpretieren.


Der Klammerausdruck bedeutet doch, wenn ADCSR gleich "1" UND

ADCSR gleich "1" sind, bleibt das Programm in der whileschleife, weil 
der

Klammerausdruck "1( wahr)" ist. Oder hänge ich mit meiner Interpretation

daneben?

ADCSR ist doch permanent grösser als "1", weil mehrere Bits dauerhaft

gesetzt sind. Ich weiss es einfach nicht, wieso ADCSR im Klammerausdruck

stehen muss. In den Tutorials und Foren habe ich keine Hilfe bezüglich

dieser Schreibweise

gefunden.

von Walter S. (avatar)


Lesenswert?

Udo Scharnitzki schrieb:
> while (ADCSRA & (1 << ADSC)) // warten, bis Wandlung fertig ist

du meinst sicher:
while (ADCSRA & (1 << ADSC)) ;

von Walter S. (avatar)


Lesenswert?

Udo Scharnitzki schrieb:
> Mir sind die logischen Verknüpfungen bekannt, aber ich kann sie
> innerhalb
> des Klammerausdrucks nicht interpretieren.

sie sind Dir wohl nicht bekannt, denn die logische Verknüpfung UND 
schreibt sich &&

Udo Scharnitzki schrieb:
> In den Tutorials und Foren habe ich keine Hilfe bezüglich
> dieser Schreibweise
> gefunden.

na ja, das kann ich mir jetzt nicht vorstellen

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.