Forum: Mikrocontroller und Digitale Elektronik ADC beim atmega32 liefert 0


von Ulrich L. (kaschpal)


Lesenswert?

Hallo zusammen,

leider habe ich ein Problem beim Auslesen des ADC mit meinem mega32:
Der returnwert von read_sensor ist immer null, egal, was am Port 
anliegt.

- Spannung direkt am Pin überprüft, liegt was an
- unterschiedliche Spannungen ausprobiert
- porta0 - porta7 durchprobiert
- Nur lesen von ADCH ausprobiert
- Takt 10 MHz

Code habe ich angehängt:
1
extern void init_sensor()
2
{  
3
4
  // adc freischalten
5
  ADCSRA = (1 << ADEN);
6
7
8
  // Frequenzteilerverhältnis auf 1/128
9
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) |  (1 << ADPS0);
10
11
12
  /* Kanal einstellen */
13
  ADMUX = SENSOR;             // SENSOR == 7
14
15
  
16
  /* Interne Referenzspannung 2.56 V */
17
  ADMUX |= (1 << REFS1) | (1 << REFS0);
18
19
20
}
21
22
23
extern uint16_t read_sensor()
24
{  
25
  uint16_t  result;
26
27
28
29
  
30
  init_sensor();
31
32
  // Messung anstoßen  
33
  ADCSRA = (1 << ADSC);
34
35
36
  // warten, bis Messung komplett
37
  while (ADCSRA & (1 << ADSC)) ;
38
39
40
  result = ADCL;
41
  result += (ADCH << 8);
42
43
44
  return result;
45
46
}

Tja, ich hoffe, jemanden von Euch ist das Problem bekannt, ich
weiss langsam wirklich nichte mehr weiter ... (adc kaputt??)

von Benedikt K. (benedikt)


Lesenswert?

Ulrich Leutner wrote:

>   // Messung anstoßen
>   ADCSRA = (1 << ADSC);     <- Da setzt du nur das ADSC Bit, löschst aber alle 
anderen

von Ulrich L. (kaschpal)


Lesenswert?

Ahhhh! Himmel! Stimmt, danke.

Bloss die schlechte Nachricht, es geht immer noch nicht.
Ich habs auch schonmal im freilaufenden Betrieb probiert, das war dann 
das gleiche ...

Inzwischen hab ich mir auch noch einen zweiten µC (baugleich) 
ausgeliehen, bei dem gehts auch nicht, also wird der ADC wohl nicht 
defekt sein ...

von Ulrich L. (kaschpal)


Lesenswert?

Kommando zurück: jetzt funktionierts. Keine Ahnung was sich jetzt 
verändert hat, aber jetzt gehts :)

Danke für die schnelle Antwort!

von Johannes M. (johnny-m)


Lesenswert?

> result = ADCL;
> result += (ADCH << 8);
Mach das nicht von Hand. Der Compiler kennt dafür ein 16-Bit-Register 
(ADC oder ADCW), das Du ohne großes Trara direkt in die entsprechende 
Variable übernehmen kannst, ohne dass Du Dich auch noch um die 
Zugriffsreihenfolge kümmern musst (die hier aber zufällig stimmt)...

von Ulrich L. (kaschpal)


Lesenswert?

OK, danke für den Tipp, mag auch schönen Code :)

Ich hab jetzt bloss grad die lezten 2 Stunden zwischen Datenblatt, den 
zwei Tutorials und anderen Codefetzen hin&hergewurschtelt und so war ich 
mir sicher, dass in der Variablen wenigstens IRGENDWAS steht, wenns 
funktioniert ...

von Johannes M. (johnny-m)


Lesenswert?

Das hier:
1
result += (ADCH << 8);
... klappt zwar in diesem Fall, weil Du Glück hast, dass es die Integer 
Promotion gibt. Aber grundsätzlich sollte man einen Wert, bevor man ihn 
über seinen eigenen Wertebereich hinaus verschiebt, auf den Zieldatentyp 
erweitern. Würde der Compiler nämlich nicht automatisch das auf der 
rechten Seite vom "=" nach int erweitern, käme immer 0 raus. Also besser 
auf Nummer sicher und
1
result += ((uint16_t) ADCH) << 8;
(abgesehen von oben gesagtem, nur als zusätzlicher Tipp).

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.