Ich werde das mal Zeile für Zeile sezieren.
Das wird vom Compiler zwar toleriert, ist aber fehleranfällig. Wenn der
Funktion nichts übergeben werden soll, sollte sie mit
initialisiert werden. Hilft bei komplexeren Programmen, wenn man mal
Funktionen verwechselt ungemein bei der Fehlersuche.
1 | uint16_t result;
|
2 |
|
3 | // interne Referenzspannung als Referenz für den ADC wählen:
|
4 | ADMUX = 0b01001000;
|
Die Variablendeklaration von result passt so.
Bei ADMUX sollte aber der Kommentar zur Anweisung passen. Schau ins
Datenblatt des ATmega16 auf Seite 217, dann siehst du, welche Referenz
du hier wirklich einstellst und welche Einstellung du hier noch
vornimmst.
Ganz allgemein sind Zuweisungen mit der "Holzhammermethode" - also in
der Form REGISTER = Zahl - eher zu vermeiden, weil man damit alles
überschreibt, was man vorher mit dem Register angestellt hat. Wie man
einzelne Bits setzt und löscht ohne dabei den Rest des Registers zu
beeinflussen, steht im AVR-GCC-Tutorial.
1 | ADCSRA = 0b00100110; // Frequenzvorteiler - "Free running Modus"
|
2 | ADCSRA |= (1<<ADEN); // ADC aktivieren
|
Auch hier gilt wieder: Holzhammermethode. Was passiert bei der oberen
Zuweisung genau? Schau ins Datenblatt auf S. 219. Dort steht, was die
einzelnen Bits bedeuten. Wie eine Zuweisung aussehen sollte, zeigt die
untere Zeile. Dort wird unabhängig von den sonstigen Stellen im Register
und auch deutlich nachvollziehbar ein Bit gesetzt.
Was neben dem Setzen von ADEN noch fehlt, damit der ADC wirklich
loslegt, ist das Setzen von ADSC (Datenblatt, S. 219).
Ganz nebenbei. Ob deine Einstellungen für den Prescaler richtig sind,
kann dir niemand sagen, solange nicht klar ist, mit welcher Taktfrequenz
dein Controller arbeitet.
1 | /* Dummy - Readout*/
|
2 |
|
3 | if (ADCSRA |= (ADIF==1))
|
4 | {
|
5 | result = ADCL+ADCH; // auf Abschluss der Konvertierung warten
|
6 | }
|
Wichtig zu wissen ist, dass ein einzelnes '=' auch in Kombination mit
den Operatoren zu '+=', '-=', '*=', '/=', %=', '&=', '|=', '^=' in C
immer eine Zuweisung durchführt, du in der Klammer hinter dem 'if' aber
eigentlich ja vergleichen willst bzw. prüfen, ob an einer bestimmten
Stelle im Register eine 1 steht. Wie man vergleicht, kannst du hier
lernen:
http://www.mikrocontroller.net/articles/Bitmanipulation#Standard_C_4
Statt
würde ich aber die Schreibweise
bevorzugen, weil man dann besser nachvollziehen kann, was hier die
Bedingung ist.
Anschließend weist du result die Summe der beiden Register ADCL und ADCH
zu, was Unsinn ist, weil du damit die Wertigkeit der einzelnen Bits
durcheinander bringst. In C solltest du dich nicht mit ADCL und ADCH
herumschlagen, sondern result einfach ADC oder ADCW zuweisen, weil der
Rest vom Compiler erledigt wird.
Das ADIF-Flag wird nicht automatisch gelöscht, von daher muss es per
Hand nach dem Auslesen des Registers wieder zurückgesetzt werden, wenn
du nicht mit echten Interrupts arbeitest. Was dafür getan werden muss,
steht auch auf S. 219 im Datenblatt. Soweit zur Initialisierungsroutine.
1 | if(ADCSRA = (ADIF==1))
|
2 | {
|
3 | ADMUX = (1<<MUX2);
|
4 | Messung5 = ADCL+ADCH;
|
5 | }
|
Für die Bedingung gilt noch immer das Gleiche: Vergleichen, nicht
zuweisen. Indem du hier statt '|=' einfach '=' verwendest, setzt du alle
Bits in ADCSRA auf 0. Sprich: ADC wird ausgeschaltet, Free Running Mode
gestoppt, Prescaler überschrieben...
In ADMUX stellst du mit der Direktzuweisung Ähnliches an. ADMUX sollte
in der Initialisierung fest eingestellt und danach nicht mehr verändert
werden, wenn es nicht nötig ist.
Die Variable Messung5 ist nirgendwo initialisiert und die Zuweisung als
Summe der beiden Register wie schon weiter oben bei 'result' unsinnig.
1 | if (Messung5>=100)
|
2 | {
|
3 | DDRB = 0b00011111;
|
4 | _delay_ms(200);
|
5 | DDRB = ob00000000;
|
6 | }
|
Die Bedingung passt so, aber was soll danach passieren? Mach dir den
Unterschied zwischen DDRx, PORTx und PINx klar. Du machst hier fünf
Anschlüsse des Ports B zu Ausgängen, wartest 200ms und hast dann eine
Anweisung, die niemand verstehen wird, weil da statt der 0 vor dem b ein
kleines o steht.