Wenn ich meinen AD-Wandler sagen will dass er:
-im FreeRunning-Mode laufen soll (ADEN=1) (ADCS=1) (ADFR=1)
-den Interrupt Flag setzen soll, aber > keinen Interrupt < auslösen soll
(ich will das Flag bei einem anderen Timer-Interrupt auslesen)
Dann muss ich doch nur (ADIE=1) setzen und kein Interrupt vom ADC funkt
mir dazwischen, weil ich ja das I-bit im SREG nicht gesetzt habe.
Ist das so erstmal richtig?
Ich würd gern bei einem anderen Interrupt (der eh zur rechten Zeit
kommt) abfragen ob die Wandlung fertig ist und dann den Wert in dieser
Interrupt-Routine weiter verarbeiten.
Ich dachte da (bei 16MHz Takt) an einem Prescaler von 128 (9.6KHz
Samplingrate bei 13 Takte/Umwandlung und 5kHz bei 25 Takte/Umwandlung)
Hi
Da geht ewas durcheinander: Mit ADIE erlaubst du den ADC-Interrupt. Das
I-Bit zeigt global einen Interrupt an. Ein ADC-Interrupt wird durch ADIF
oder so ähnlich angezeigt.
MfG Spess
Wenn das I-Bit im SREG gelöscht (0) ist, wird gar kein Interrupt mehr
ausgelöst. Wird das I-Bit wieder gesetzt, fallen alle in der
Zwischenzeit ausgelösten Interrupts an. Den Interrupt des ADC kannst Du
sperren, indem Du ADIE auf 0 läßt. Die Wandlung ist fertig, wenn ADIF
gesetzt ist. Dieses Flag mußt Du nach dem Auslesen der
ADC-Ergebnis-Register manuell auf 1 setzen, um es zu löschen und als
Indikator für das nächste Wandlungsende zu nutzen. Im Free-Running Mode
besteht, wenn Du den ADC-Interrupt nicht nutzt, die Gefahr, daß Du
Wandlungen verpaßt.
Danke für die Erklärung, lass ich ADIE auf null und lösch dann einfach
ADIF durch setzen auf eins.
Hier hab ich etwas geschrieben, ich hoffe es macht das was es soll.
>>Hab ich irgend was vergessen?
1) ja, du kannst ADSC nämlich nicht löschen, das passiert aber
automatisch, wenn der ADC abgescaltet wird
2) ja, setMux() schaltet den ADC nicht wieder ein
3) ja, Was macht deine get_ADC Funktion, wenn der ADC noch nicht fertig
ist? (du hast keine Warteschleife oder einen brauchbaren
Rückgabe-'Code').
Das ganze könnte man z.B. mit dem ADC-complete interrupt lösen:
- eine globale Var. enthält den nächsten Kanal.
- eine Weitere enthält Flags:
- eines für 'fertig'
- ... (fällt mir grad nichts weiter ein ;) )
- der ADC wird einmal gestartet (als "single conversion"!)
- die ISR
- liest das Ergebnis aus (in die Globale Var.)
- stellt den neuen Kanal ein
- startet die nächste Wandlung
- get_adc_val:
- fragt das flag ab, wenn das gesetzt ist:
- setzt den nächsten kanal
- gibt das Ergebnis zurück
hth. Jörg
>> Wird mir der Compiler das get_ADC() weg optimieren [...]
ein kurzer Test sagt: Nein (Test im Anhang)
- ist aber auch nicht so tragisch: Wandlung starten und dann abwarten
geht kaum schneller (Eine Wandlung dauert min. 13,5 * 128(-> Prescaler)
Takte ), da kommt es doch auf 6-10 unnötige (ASM-)Anweisungen (Aufruf,
Einlesen etc.) nicht wirklich an, oder?
hth. Jörg
Hab mir jetzt die neue AVR Studio Version installiert und festgestellt
dass die Speicher- Nutzung/Belegung angezeigt wird.
Ist das erst seit 4.13 Build 528 so ?
AVR Memory Usage
----------------
Device: atmega8
Program: 444 bytes (5.4% Full)
(.text + .data + .bootloader)
Data: 5 bytes (0.5% Full)
(.data + .bss + .noinit)
Build succeeded with 0 Warnings...
Also morgen kann ich jedenfalls testen :-)
So, hab es jetzt alles aufgebaut.
1.) Läuft aber noch nicht :-(
Über "PORTD" lass ich mir den ADC-Wert ausgeben (mit Leuchtdioden)
An ADC7 hab ich mein Poti.
Ich kann drehen wie ich will, das Signal scheint für mein Programm immer
High, 100%, 5V zu sein.
An ADC7 liegen jetzt 0.63V an (mit Multimeter gemessen) und während der
Simulation in AVR Studio war auch Kanal 7 ausgewählt.
2.) (merkwürdiges Problem)
ADSC wird bei der Simulation immer gelöscht und zwar in get_ADC_8()
nachdem ich ADIF lösche.
Als Fehlerumgehung hab ich ADSC einfach in get_ADC_8() nochmal gesetzt,
eigentlich läuft mein AD-Wandler doch im FreeRunning Modus ... da müsste
ich dieses bit eigentlich nicht immer wieder neu setzen.
1
main:
2
-----
3
4
main(){
5
uint8_tadc_wert;
6
7
set_ADC_8_Kanal(7);// Teste ADC auf Kanal 7 (Pin 22)
Es muss grundsätzlich immer das ADCH ausgelesen werden! Steht auch im
Datenblatt. Abgesehen davon, dass es sinnfrei ist, nur das Low-Byte
auszuwerten, wird das Ergebnisregister erst wieder freigegeben, wenn
ADCH gelesen wurde. Wird nur ADCL gelesen, dann kann der ADC keinen
neuen Wert im Ergebnisregister ablegen. Ist klar, dass Du immer den
selben Wert ausliest. Wenn Du nur 8 Bit Auflösung brauchst, dann setze
ADLAR und lies nur das High-Byte aus. Dann gibts auch keine Probleme.
Deine switch-case Abfrage macht m.E. auch nicht viel Sinn. Was soll die
Division durch 32 und das Abfragen auf 0...7 ?
Dass das ADSC gelöscht wird, hängt möglicherweise damit zusammen, dass
der ADC im Simulator nur teilweise unterstützt wird. In Hardware sollte
das nicht passieren, wenn der Free Running Mode korrekt aktiviert wurde.
@ johnny-m
Danke, hab mir das Datenblatt durchgelesen und viel Zeit dafür
aufgewendet.
War aber wohl noch nicht genug.
Dann setze ich ADLAR ... hab mich schon gefragt wozu dieses bit gut ist.
Zu der Division durch 32, das ist quasi ein bit-shift nach links.
z.B.: 10110011 >> 5 = 00000101
--- ---
Das sind dann Zahlen von 0 bis 7 (3 Bit)
dann brauch ich keine 8 if(zahl<x && zahl>y) Abfragen ...
Ich will nur eine LED an PORTD leuchten lassen, je nach Wert. Bei 0 soll
PinD0 high sein und bei 255 soll PinD7 high sein.
Chris J. wrote:
> Zu der Division durch 32, das ist quasi ein bit-shift nach links.>> z.B.: 10110011 >> 5 = 00000101> --- ---> Das sind dann Zahlen von 0 bis 7 (3 Bit)> dann brauch ich keine 8 if(zahl<x && zahl>y) Abfragen ...
Jau, ist mir mittlerweile auch aufgegangen... Hatte es nur überflogen.
Aber:
Wie Travel Rec. anmerkte: ADCH muss immer gelesen werden, unabhängig
von irgendwelchen anderen Einstellungen.
@ johnny-m
Hab's jetzt so gemacht und hat funktioniert.
> Dass das ADSC gelöscht wird
Das hat in der Simulation nicht funktionier und der Mega8 hat sich wie
die Simulation verhalten und ADSC intern auch gelöscht.
Also wird ADSC bei fehlerhaften auslesen der ADCL/H Register gelöscht.
@ Travel Rec.
Ich weiß jetzt wie es richtig geht :-)
@ Jörg X.
Genau das werde ich jetzt machen.
Muss dazu nur noch meine Testplatine umlöten und zusätzlich 3 Taster
anlöten.
Ich hab jetzt aber noch etwas festgestellt, wenn ich den Poti drehe und
die Leuchtdioden beobachte hab ich nicht das Verhalten welches ich mir
vorgestellt habe.
z.B.: Die LED an Pin3 ist an, jetzt dreh ich weiter und die LED an Pin3
wird sozusagen gedimmt und die LED an Pin4 wird heller.
Wie kann das sein, ich dachte das ist eine rein logische Angelegenheit.
Kann es sein dass die Versorgungsspannung/Referenzspannung etwas
schwankt und zeitweise der Pin3 und der Pin4 high sind? Sozusagen
Pulsweitenmoduliert?
Hab's einfach mal getestet, es sind bei mir 2.05kHz die an den beiden
Pin's dann anliegen. (Also sie schalten voll durch!)
Meine Abblockkondensatoren:
VCC - 330µF (Versorgung von USB(5V, GND) )
AVCC - 330µF + 470nF(mit Spule zu VCC und kleine SMD-Spule nach GND)
... ob da was schwingt?