Hallo!
Ich verwende den ATtiny84A für eine LED-Ansteuerung mit PWM, auch der
ADC und Timer werden benutzt.
Datenblatt:
http://www.atmel.com/Images/doc8183.pdf
Ein interner Oszillator hat 8MHZ für den Takt, ist defaultmäig
aktiviert. Auch die Fuse CKDIV8 ist defaultmäßig gesetzt, der µC läuft
also mit 1 MHZ Takt. Ich habe die ganzen Prescaler für PWM, Timer, ADC
Takt auf diesen Takt bezogen (z.B. beim Timer: Prescaler 8 ergibt dann
einen Takt von 125kHz). So weit so gut...
Nun besitzt der µC auch einen internen Oszillator mit 128kHz, welchen
ich gerne aus Energiespargründen verwenden würde.
Meine Fragen dazu:
1.) Kann ich das nur beim Programmiervorgang über die Fuse umstellen
oder geht das auch, indem ich softwaremäßig in CKSEL Register was
reinschreib?
2.) Werden die ganzen Takte für PWM, Timer, ADC nun auf diesen Takt
bezogen? Muss ich also die Prescaler dementsprechend anpassen?!
3.) Wie ist das dann mit dieser CKDIV8-Fuse, muss ich diese auch
deaktivieren damit der Takt bei 128 kHz bleibt?
Vielen Dank!
Seite 32 des Datasheet:
das DIV8 Fuse verursacht, dass der Clock Prescaler mit 8 initialisiert
wird, d.h. das gilt auch für den 128k Oszillator.
Dementsprechend gilt das für alles, was von der System Clock abhängt.
Wenn Du es also nicht haben willst, musst Du die Fuse rausnehmen beim
Programmieren.
Die 128k Modus setzt Du über Fuse, kannst Du nicht im Code "von innen"
machen.
Du kannst aber den Prescaler im laufenden Betrieb rausnehmen und von
128/8 auf 128k kommen nachdem Dein Progrämmchen gestartet hat.
D.h. DIV8 ist gesetzt, AVR startet mit 128k/k Hz, dann Prescaler setzen,
Du hast 128k Hz.
Ok danke für die Antwort...
Ich programmiere üpber DWenable. Bevor ich die Fuses setze, habe ich
während des Debuggens "Disable DebugWire and Close" ausgewählt
(Debug-Menü), damit die DWEN-Fuse wieder gelöscht wird und ich auf die
Fuses zugreifen kann.
Dann habe ich unter Tools->Device Programming -> Fuses die CKDIV8 Fuse
gelöscht und bei SUT_CKSEL 128kHz internen Oszillator ausgewählt. Dann
bin ich auf "Programm" und seit dem kann ich die Fuses nicht mehr
lesen?!
Ich kann jedoch weiterhin im DebugWireEnable Modus programmieren. Was
habe ich falsch gemacht?
Danke
Hans Peter schrieb:> Ok danke für die Antwort...>> Ich programmiere üpber DWenable. Bevor ich die Fuses setze, habe ich> während des Debuggens "Disable DebugWire and Close" ausgewählt> (Debug-Menü), damit die DWEN-Fuse wieder gelöscht wird und ich auf die> Fuses zugreifen kann.>> Dann habe ich unter Tools->Device Programming -> Fuses die CKDIV8 Fuse> gelöscht und bei SUT_CKSEL 128kHz internen Oszillator ausgewählt. Dann> bin ich auf "Programm" und seit dem kann ich die Fuses nicht mehr> lesen?!>> Ich kann jedoch weiterhin im DebugWireEnable Modus programmieren. Was> habe ich falsch gemacht?>> Danke
Wenn ich das jetzt richtig sortiert habe, kannst du im ISP-Mode nicht
mehr zugreifen, weil dein ISP-Takt mit 125KHz zu hoch ist. Der ISP muss
<=1/4 CPU-Takt sein.
Aber zu deinem Hauptanliegen:
Du willst doch keine 2-mA-Leds dimmen. Den Löwenanteil des Stromes
ziehen deine Leds aus der Batterie. Das, was der Controller
währenddessen braucht, sind doch Peanuts. Und das bleiben auch bei 8MHz
noch Peanuts.
Lass dieses Taktgefriemel. Schalte das Teil aus, wenn die Leds nicht
leuchten oder setzt den Controller in den Powerdown-Seepmode. Und gut
ist.
Und wenn das Ganze an einem Netzteil hängt, lohnt es sich nicht, auch
nur eine Sekunde über Stromsparmodi nachzudenken.
mfg.
Ok, jetzt ist mir wieder einiges klarer...
Wohl, ich will 2 mA LEDs dimmen. Insgeamt fließen um die 5 mA, zahlt es
sich in diesem Fall auch nicht aus, den Takt runterzustellen?
Dankesehr :)
Hans Peter schrieb:> Ok, jetzt ist mir wieder einiges klarer...>> Wohl, ich will 2 mA LEDs dimmen. Insgeamt fließen um die 5 mA, zahlt es> sich in diesem Fall auch nicht aus, den Takt runterzustellen?>> Dankesehr :)
Guck mal ins Datenblatt:
21.2.1 Current Consumption in Active Mode
Bei 2,7V und das reicht für deine Leds dicke aus, beträgt der
Unterschied zwischen 128KHz und 1MHz ca. 0,2 mA. Also in deinem Fall
etwa 5,1 zu 5,3. Der Preis dafür ist, daß du aus deinem Controller eine
total lahme Gurke machst.
mfg.
Hallo!
Ich habe nun doch versucht und es geschafft, die Taktfrequenz auf 128
kHz umzustellen. Ich verwende eine Batterie mit 1,5V, die mit einem
Step-Up auf 5V für die µC Versorgung gebracht wird... Dieser
funktioniert bis 0,7V und in diesem Bereich werden die Ströme am Eingang
höher um die 5V zu halten (um die 40mA). Am Ausgang des µC habe ich 4
LEDs (2 Parallelstränge mit jeweils 2 LEDs und einen Rv) udn einen
zusätzliche LED. Durch all diese LEDs fließe ca 2 mA, also insgesamt ca.
6mA. Zusätzlich hängen am Ausgang des Step-UP(5V) nur noch der µC selbst
und externe Beschaltungen (Externe Referenz für ADC,...).
Da es in diesem Bereich, in dem die Batteriespannung immer kleiner wird,
größere Unterscheide im Strom gibt (zwischen 1MHz Takt und 128kHz Takt,
ca 10mA), würde ich es mit den 128kHz trotzdem gerne versuchen.
Die beiden Timer habe ich ohne Prescaler initialisert (laufen also mit
128kHz) den ADC Takt habe ich mit einen Teiler von 2 auf 64kHz
eingestellt (sollte laut Datenblatt in dem Bereich liegen). Die CKDIV8
Fuse habe ich ebenfalls rausgenommen, um bei den 128kHz zu bleiben.
Timer und ADC funktionieren soweit richtig, aber der Programmablauf ist
sehr langsam. Alein die Initialisierungsphase:
1
DDRA|=(1<<PA7)|(1<<PA3);// output
2
DDRB|=(1<<PB2);// output
3
4
PORTA&=~(1<<PA3);// low
5
//PORTB |= (1 << PB1); // high
6
7
// Timer0 -> PWM (8 Bit)
8
TCCR0A|=(1<<COM0A1)|(1<<COM0B1)|(1<<WGM00);
9
TCCR0B|=(1<<CS00);// prescaler 1 -> 128kHz
10
TCNT0=0;
11
OCR0A=0// compare value 0 -> duty cycle 0
12
OCR0B=0;
13
14
// Timer1 -> general purpose timer (16 Bit)
15
TCCR1B|=(1<<CS10);// prescaler 1 -> 128 kHz
16
TIMSK1|=(1<<TOIE1);// enable interrupt for timer overflow
17
TCNT1=0;// timer value initialization
18
19
20
// ADC
21
PRR&=~(1<<PRADC);//disable Power Reduction for ADC
dauert sehr lange (ca 10 Sek.) Auch auf Tastendrücke währned des
Betriebes reagiert der µC erst nach ca 2 Sek...
Nun meine Frage: Ist das die "lahme Ente" von der Du (Thomas) gesprochen
hast? Ist das prinzipiell wegen der niedrigen Taktfrequenz von 128 kHz
oder liegts am Code?
Danke, lG
Da hab ich mal deine ganzen _delay in Verdacht.
Ob die delay Makros mit der niedrigen Taktfrequenz (du hast doch F_CPU
auf 128000 gestellt?) überhaupt klar kommen, weiß ich nicht.
Hans Peter schrieb:> Nun meine Frage: Ist das die "lahme Ente" von der Du (Thomas) gesprochen> hast? Ist das prinzipiell wegen der niedrigen Taktfrequenz von 128 kHz> oder liegts am Code?
Ich denke eher es liegt am Code.
128kHz sind zwar in Relation recht langsam. Es sind aber immer noch rund
100-tausend Operationen pro Sekunde.
Ok danke für den Hinweis... Jetzt weiß ich dass es sich lohnt
weiterzuschaun...
Hmmm... aber woran könnte das liegen? Kann ich bei der Initialisierung
irgendwas besser machen?
Den Haupthinweis hast du doch schon.
_delay_ms
Prüf halt mal mit einem Testprogramm nach, ob die dadurch erreichten
Zeiten überhaupt stimmen. Die paar Zuweisungen an Register sind ganz
sicher nicht das Problem.
OK, danke...
Die delay-Befehle scheinen viel zu lange zu dauern. Aber auch der oben
angeführte Code bis zum ersten delayms(1) dauert ca 2 Sek... Ist das OK?
Ich habe nun am Beginn #define F_CPU 128000 eingefügt, das ändert aber
nichts :(
Hans Peter schrieb:> OK, danke...>> Die delay-Befehle scheinen viel zu lange zu dauern. Aber auch der oben> angeführte Code bis zum ersten delayms(1) dauert ca 2 Sek... Ist das OK?>> Ich habe nun am Beginn #define F_CPU 128000 eingefügt, das ändert aber> nichts :(
Mach halt mal einen Test
1
#define F_CPU 128000
2
3
#include<avr/io.h>
4
#include<util/delay.h>
5
6
7
intmain()
8
{
9
// *******************************
10
11
DDRB|=(1<<PB2);// so schnell wie möglich eine LED einschalten
12
PORTB&=~(1<<PB2);
13
14
// *******************************
15
16
DDRA|=(1<<PA7)|(1<<PA3);// output
17
DDRB|=(1<<PB2);// output
18
19
PORTA&=~(1<<PA3);// low
20
//PORTB |= (1 << PB1); // high
21
22
// Timer0 -> PWM (8 Bit)
23
TCCR0A|=(1<<COM0A1)|(1<<COM0B1)|(1<<WGM00);
24
TCCR0B|=(1<<CS00);// prescaler 1 -> 128kHz
25
TCNT0=0;
26
OCR0A=0// compare value 0 -> duty cycle 0
27
OCR0B=0;
28
29
// Timer1 -> general purpose timer (16 Bit)
30
TCCR1B|=(1<<CS10);// prescaler 1 -> 128 kHz
31
TIMSK1|=(1<<TOIE1);// enable interrupt for timer overflow
32
TCNT1=0;// timer value initialization
33
34
35
// ADC
36
PRR&=~(1<<PRADC);//disable Power Reduction for ADC
Ich hab angenommen, dass an PORTB, Pin 2 eine LED sitzt. Wenn das bei
dir anders ist, dann tausch das eben aus.
Die Zeit nach dem Einschalten, bis die LED ganz am Anfang von main()
eingeschaltet wird, kann man zwar noch verkürzen, aber ansonsten ist die
mehr oder weniger vorgegeben. Denn das C-Runtime System hat auch einiges
zu tun, bis es die Kontrolle an main() abgibt
Vor der Hauptschleife wird die LED dann noch mal umgeschaltet, die Zeit
dazwischen, das ist die Zeit, die für deine Initialisierungen gebraucht
wird. Ich würde mal erwarten, dass das nicht allzulang ist. Denn auch
bei 128kHz werden die 20 oder 30 Operationen in weniger als 1
Millisekunde abgearbeitet.
Und dann ist da noch die Hauptschleife, in der es darum geht, ob
_delay_ms mit 128kHz überhaupt korrekte Ergebnisse liefert.
Ganz abgesehen von der Fragestellung, wozu man _delay_ms überhaupt
braucht (*). Delays sind in einem Programm selten die Lösung. Sie sind
aber oft das Problem.
(*) mit der Ausnahme von delays im µs Bereich, die man für Protokolle
schon mal braucht, bzw. delays am Programmanfang um die
Selbstinitialisierung externer Komponenten, wie zb LCD, abzuwarten.
Mit deinem Testprogramm funktioniert alles wie es soll... Die
Initialisierungsphase ist sehr kurz und danach blinkts im 2Hz-Takt...
Aber wenn ich mein Programm dann wieder starte hab ich wieder das
gleiche Problem... Kann das Problem eventuell daran liegen, dass der ADC
im FreeRunningModus läuft (mit 64kHz). Der Haupttakt liegt ja nun bei
128kHz, kann das sein, dass nun nach jedem zweiten Befehl eine ADC
Wandlung durchgeführt wird?
Danke!!
Hi
>Kann das Problem eventuell daran liegen, dass der ADC>im FreeRunningModus läuft (mit 64kHz).
Da alle 26 Controllertakte ein Interrupt ausgelöst wird, durchaus
möglich. Wie sieht deine ISR aus?
MfG Spess
Hi
Interessant wäre das Assembler Listing. Aber wenn das grob geschätzt 20
Takte braucht, dann bleiben nur 6 Takte für das restliche Programm. Das
merkt man schon.
An deiner Stelle würde ich statt Free Running den ADC mit dem
Timer0-Overflow triggern. Kannst du mit den ADTS-Bits von ADCSRB
einstellen.
MfG Spess
Hmm, danke vielmals für den Hinweis, werde ich mal versuchen!
Im Zuge des Debuggens ist mir nun auch aufgefallen, dass IF-Abfragen
relativ lange (ca 1s!!) dauern, was auch sehr stark zu verzögerungen
beiträgt.. Wie kann das sein?
lG
Conny G. schrieb:> Die 128k Modus setzt Du über Fuse, kannst Du nicht im Code "von innen"> machen.
Man kann aber den normalen 8-MHz-Oszillator nehmen und den mit dem
Prescaler herunterteilen. Auf diese Weise kommt man bis zu 32 kHz
hinab.
Dürfte deutlich handlicher sein als das Gefummel mit den Fuses.
Eigentlich ist es aber nicht sinnvoll, so langsam zu takten. Besser
ist es, stattdessen die CPU während der Wachphase schneller laufen
zu lassen und dann schlafen zu legen.
_delay_ms benutzt eine Loop, die mit 4 Takten pro Zyklus arbeitet.
Bei 128 kHz ergibt das eine Granularität von 31 µs. Eigentlich sollte
sich damit ein Delay von 1 ms brauchbar genug einrichten lassen.
Dumme Frage: die Compiler-Optimierung hast du aber aktiviert, ja?
Hans Peter schrieb:> wo kann ich das im AVR Studio 6 nachschaun/einstellen?
Sorry, da kenn ich mich nicht aus damit.
Muss irgendwo ein -Os oder -O1 auf der Compiler-Kommandozeile
auftauchen.
Hans Peter schrieb:> relativ lange (ca 1s!!) dauern, was auch sehr stark zu verzögerungen> beiträgt.. Wie kann das sein?
An deinem Code!
(So wie immer. Und auch so wie immer, zeigst du den nur in
homöopathischen Dosen, erwartest aber, dass wir dir ganz genau sagen wo
die Probleme liegen)
Wenn bei meinem Code die _delay_ms korrekt arbeiten, in deinem Code aber
nicht, dann könnte das an der Reihenfolge liegen
Falsch
Das define F_CPU ist vor dem include<delay...> definiert, das mit den
delays funktioniert nun auch korrekt...
Wenn ich den ganzen Code rein stelle, wird es wohl sehr
unübersichtlich... Es liegt wahrscheinlich wirklich daran, dass der ADC
im FreeRunningModus läuft... wenn ich in der ISR vom ADC einen
breakpoint setze, komm ich gar nicht mehr raus...
Ich bin gerade dabei, den ADC auf den Timer0(8bit) zu triggern. das
erreiche ich, wenn ich das ADTS2 Bit im ADCSRB register setze. Den Timer
0 hab ich aber für PWM initialisiert, kann ich trotzdem einen Timer0
overflow interrupt aktivieren? Das würde ich mit TIMSK |= (1<<TOIE0)
machen. Muss ich dann in der ISR des Timer0 noch was machen oder wandelt
der danns chon jedes mal, wenn Timer0 überläuft? (das ADSC bit im ADSCRA
ist gesetzt)...
Vielen Dank!
Hi
>Den Timer>0 hab ich aber für PWM initialisiert, kann ich trotzdem einen Timer0>overflow interrupt aktivieren?
Ja, das beeinflußt die PWN nicht.
>Muss ich dann in der ISR des Timer0 noch was machen
Nein.
>oder wandelt der danns chon jedes mal, wenn Timer0 überläuft?
Ja.
>(das ADSC bit im ADSCRA ist gesetzt)...
Brauchst du nicht setzen. Das wird bei Free Running nur zum Starten
gebraucht.
MfG Spess
Folgendes Problem:
sobald ich die Zeile //TIMSK0 |= (1 << TOIE0); auskommentiere, komm ich
nicht mehr aus der init funktion raus (zurück in die main). Ich muss den
Interrupt des Timer0 aber aktivieren, damit der ADC getriggert wird.
Wenn ich den Kommentar drin lasse, funktioniert der Ablauf ganz normal,
aber der ADC interrupt wird (verständlicherweise) nie ausgelöst! Ich
nehme an, dass er bei diesem Befehl TIMSK0 |= (1 << TOIE0); immer
irgendwie neu startet und aus der main wieder in die init hüpft...
Ich habe das nun so verstanden, dass ich den ADC nicht explizit starten
muss, wenn er auf eine Timeroverflow getriggert ist. Was mache ich
falsch?
Danke!!!
Hans Peter schrieb:> sobald ich die Zeile //TIMSK0 |= (1 << TOIE0); auskommentiere, komm ich> nicht mehr aus der init funktion raus (zurück in die main).
Und. Hast du auch eine ISR für alle Interrupts die du frei gibst.
> Ich muss den> Interrupt des Timer0 aber aktivieren, damit der ADC getriggert wird.
Ganz ehrlich.
Lass doch den ganzen Autotrigger Autotrigger sein.
Was ist denn falsch daran, wenn du in der Hauptschleife den ADC
anstösst, der wandelt, du wartest auf das Ergebnis und wenn es fertig
ist holst du es dir ab.
Einfach, simpel und funktioniert.
Muss ich für jeden Interrupt, den ich freigebe, auch eien ISR
implementieren??? Das hab ich für den Timer0Overflow nicht gemacht, ich
habe ihn nur aktiviert. Wenn das so ist, dann implementier ich dis ISR
für TimeroOverflow als leere Funktion... und wenn er dann überläuft wird
der ADC getriggert.
Was meinst du mit deiner zweiten Aussage? meinst du damit den
FreeRunning mode oder einfach dass ich immer nach eienr gewissen zeit
eine wandlung manuell starte?
Danke, lG
Hi
C ist nicht meine bevorzugte Programmiersprache.
Das sei() am Anfang der Initialisierung ist nicht sehr sinnvoll. Mach es
ans Ende.
Hast du eine ISR für den Timer0 Overflow und bist du sicher, das die
nicht wegoptimiert (Weiss nicht, ob das möglich ist) wird, wenn leer?
MfG Spess
Hans Peter schrieb:> Muss ich für jeden Interrupt, den ich freigebe, auch eien ISR> implementieren?
Selbstverfreilich. Wofür soll denn sonst der Interrupt gut sein?
> ??
Deine Fragezeichentaste klemmt. ;-)
> Das hab ich für den Timer0Overflow nicht gemacht, ich> habe ihn nur aktiviert.
Dann bekommst du beim ersten Overflow einen Sprung auf die Adresse 0,
denn das ist als default-ISR hinterlegt.
> Wenn das so ist, dann implementier ich dis ISR> für TimeroOverflow als leere Funktion...
Dafür gäbe es den Makro EMPTY_ISR(). (*)
> und wenn er dann überläuft wird> der ADC getriggert.
Dafür brauchst du aber keinen Interrupt. Der Überlauf selbst ist der
entsprechende Triggerpunkt für den auto-trigger-Modus. Der Überlauf
selbst erfolgt (sofern der Timer läuft) ganz und gar auch dann, wenn
man dafür keinen Interrupt aktiviert. Was sollte auch sonst mit dem
Timer in dem Moment passieren, wo die Zählweite erreicht ist und der
nächste Taktimpuls ankommt? ;-)
(*) Es kann manchmal Sinn haben, eine leere ISR zu haben für einen
Interrupt, der zwar freigeschaltet ist, aber sonst nicht behandelt
werden muss. Das ist beispielsweise dann der Fall, wenn der
Interrupt dazu genutzt wird, den Controller aus dem Schlaf aufzuwecken,
aber sonst keine weitere Aktion in dem Moment nötig ist.
Hi
>Dafür brauchst du aber keinen Interrupt. Der Überlauf selbst ist der>entsprechende Triggerpunkt für den auto-trigger-Modus.
Nein. Das Overflow-IR-Flag triggert den ADC. Man kann das natürlich auch
im ADC-Interrupt manuell zurück setzen.
MfG Spess
Hans Peter schrieb:> Was meinst du mit deiner zweiten Aussage? meinst du damit den> FreeRunning mode
Ich meine genau den Free Running Mode.
Auf der einen Seite bremst du deinen µC her, dass es nicht mehr
feierlich ist, auf der anderen Seite bist du erpicht darauf, den ADC
freilaufend (also möglichst schnell laufend) zu haben. Mit allen
Problemen die sich daraus ergeben, wie zb das du nicht weißt wie alt das
letzte Andlungsergebnis ist, dass du beim Zugriff auf das
Wandlungsergebnis eine Sicherung für den atomaren Zugriff brauchst.
Weltklasse, jetzt funktionierts!
DANKE Euch vielmals!
Jetz ist mir das mit der ISR und dem Overflow auch klar. Was mir
allerdings nicht klar ist, ist der Fehler, warum es nicht funktioniert
hat:
Es ist die fehlende ISR des Timer0Overflow.
Mir ist klar, dass der ADC nun auf eienn Overflow getriggert ist, aber
es funktioniert nicht, wenn ich
1
TIMSK1|=(1<<TOIE1);// enable interrupt for timer overflow
und die ISR weglasse.
Wenn der Interrupt aktiviert und die ISR vorhanden ist (kann auch leer
sein) funktioniert alles perfekt! Anscheinend ist das doch nicht auf
eienn Overflow, sondern auf den interrupt getriggert?!
Wie auch immer, es funktioniert jetz und ich versteh nun auch, warum er
ohne die ISR immer zum Anfang zurückgesprungen ist!
DANKE!
>TIMSK1|=(1<<TOIE1);// enable interrupt for timer overflow
2
>
> und die ISR weglasse.>
Weil das Ereignis ein Interrupt Flag setzt.
Aufgrund dieses gesetzten Interrupt Flags werden dann die weiteren
Aktionen eingeleitet:
Ist es gesetzt, dann wird die ISR angesprungen
Wenn du genau liest, dann ist es der Vorgang des Setzens, der den ADC
triggert.
D.h. wenn das Flag erst mal gesetzt ist, dann muss es auch gelöscht
werden.
Entweder du machst das von Hand oder aber der µC macht das. Wie macht
der µC das automatisch? Indem er in die ISR springt. Durch den Aufruf
der zugehörigen ISR wird das Flag wieder gelöscht.
Löscht du es aber nicht, weder auf die eine noch auf die andere Weise,
dann wird der ADC nicht mehr getriggert. Denn wenn es gesetzt ist, dann
kann es ja nicht wieder gesetzt werden. Der ADC spricht aber auf genau
diesen VOrgang, das Setzen des Flags an.
spess53 schrieb:>> Dafür brauchst du aber keinen Interrupt. Der Überlauf selbst ist der>> entsprechende Triggerpunkt für den auto-trigger-Modus.>> Nein. Das Overflow-IR-Flag triggert den ADC.
Ah, OK, jetzt sehe ich es auch. Das hamm'se gut im Text versteckt:
1
… A conversion
2
will be triggered by the rising edge of the selected Interrupt Flag. …
Handelt es sich dabei um das TOV0-Flag im TIFR0-Register?
Im Datenblatt stehtm, dass ich dieses Flag setzen muss, damit es
gerlöscht ist. Gehe ich richtig ind er Annahme, dass ich einfach in der
ISR des ADC dieses Flag setze?
Übrigens: Ich hab jetzt noch mal versucht auf den Free-Running mode
umzuschalten. Das funktionietr nicht. Ich nehme an, dass die
Taktfrequenmz mit 128kHz im Vergleich zu den 64kHz des ADC einfach zu
gering ist...