Hallo,
ich verzweifle gerade an einer einfachen ADC-Schaltung bzw. an dem Code.
Ich habe mich an die beiden ADC Tutorial von dieser Seite gehalten und
meiner Meinung nach eigentlich alles richtig gemacht und trotdem will es
nicht.
Ich nutze das Olimex Board für den Controller
AT90CAN(https://www.olimex.com/Products/AVR/Development/AVR-CAN/). Zur
Zeit sind noch ein LCD an Port B und C und CAN-Bus PD5 und PD6 aktiv.
Port F (ADC-Port)ist komplett als Eingang ohne Pull-Ups eingestellt.
Debugging mit AVR JTAG ICE3 über den JTAG Port auf dem Board.
In meiner Init-Methode wähle ich zunächst Channel 2 (Pin 2 Port F), dann
die Reverenzspannung (AVCC with external capacitor on AREF pin).
Und hier bin ich schon nicht sicher ob ich alles richtig mache:
Auf Seite 7 der Manual sieht man im Schaltplan eine Lötbrücke an AVREF
(siehe Link). Diese habe ich geschlossen und seitdem 5V zwischen AVREF
und AGNG liegen. Meine Versorgungsspannung liegt später bei 11 bis 13,7V
(Autobatterie), aber z.Z. bei 12V über Tischnetzteil. Als Last dient
eine 8kOhm Potentiometer
(http://www.novotechnik.de/uploads/tx_extprodfind/TX2_Gelenkkopf.pdf),
dessen äußere Anschlüsse an AVREF und AGNG anliegen. Mittelschleifer an
PF2.
Dann stelle ich den Presscaler auf 128. Weil 16MHz/200kHz = 80 also
nächster Precaler 128 (wie hier erklärt:
http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC)
Anschließend starte ich eine Wandlung, warte das Ende ab und lese dann
erst low, dann high byte aus.
1 | void ADC_init(void)
|
2 | {
|
3 | //Channel select
|
4 | ADMUX=0x02;
|
5 |
|
6 | //REFS1 REFS0 Voltage Reference Selection
|
7 | //0 0 AREF, Internal Vref turned off
|
8 | //0 1 AVCC with external capacitor on AREF pin
|
9 | //1 1 Internal 2.56V Voltage Reference with external capacitor on AREF pin
|
10 | ADMUX |= (1<<REFS0);
|
11 |
|
12 | //Set Prescaler Division factor to 128 (16MHz CPU)
|
13 | //Enable ADC
|
14 | ADCSRA |= (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
|
15 |
|
16 | //Read one value to warm up ADC
|
17 | //Start single conversion
|
18 | ADCSRA |= (1<<ADSC);
|
19 | //Wait to end convention
|
20 | while(ADCSRA & (1<<ADSC));
|
21 |
|
22 | ad_l = ADCL;
|
23 | ad_h = ADCH;
|
24 | }
|
Meine Read-Methode führe ich in der Main-Loop einmal die Sekunde
(_delay_ms()) aus. Und gebe dort das Ergebniss über CAN aus. In der
Methode selbst noch über LCD. Die Zahlendarstellung von LCD und CAN ist
getestet und korrekt.
1 | uint16_t ADC_read(void)
|
2 | {
|
3 | //Start single convertion
|
4 | ADCSRA |= (1<<ADSC);
|
5 | //Wait to end convention
|
6 | while(ADCSRA & (1<<ADSC));
|
7 |
|
8 | ad_l = ADCL;
|
9 | ad_h = ADCH;
|
10 |
|
11 | LCD_displayInt8(3,0,ad_h);
|
12 | LCD_displayInt8(3,2,ad_l);
|
13 |
|
14 | ////Return full scaled value
|
15 | return (ad_h<<8) + ad_l ;
|
16 | }
|
Nun bekomme ich aber immer nur Null als Ergebniss. Egal auf welchem
Channel. Auch dann wenn ich die Reverenspannungseinstellung ändere. Und
z.B. dann den +5V-PIN am Board als Eingangsspannung nutze. Ich habe auch
das selbe vorher ohne geschlossene Lötbrücke getestet(Dann lag aber
keine Spannung an AVREF). Ebenso auch nochmal mit einem komplett neuen
Board. Trotzdem immer nur Null.
Mach ich irgendwo einen dummen Fehler den ich einfach nicht sehe. Ich
freu mich über Hilfe.
LG