Hallo,
ich habe grosse Probleme mit dem Timing meines Programmes, die
Timerlaenge schwankt aus mir nicht erklaerbaren gruenden unregelmaessig
hin und her.
Das Programm laeuft wie folgt ab:
Timer A wird gestartet und ruft Timer B aus, der vier mal innerhalb
Timer A durchlaufen wird. Innerhalb Timer B wird die ADC Routine
ausgefuehrt und nach dem viermaligen durchlaufen ein Mittelwert gebildet
der dann via Serieller Schnittstelle(9600baud) verschickt wird.
Auch wenn ich das versenden abschalte, das Timing stimmt einfach nicht..
Sieht jemand von euch den Fehler?
Vielen Dank
Frank
Also das kommt mir sooooo bekannt vor, dass ich ja fast Troll-Alarm
auslösen möchte. Aber wie immer, denke ich ja zuerst mal nur das Beste:
Alles schon dagewesen:
Beitrag "[MSP430] Probleme mit dem Mikrocontroller"
Es fehlt die gesamte Initialisierung der Takterzeugung. Ohne die wird
der MSP430 vom internen RC-Oszillator "DCO" mit einem Takt von irgendwas
um 1 MHz versorgt.
Du musst klären, was die Taktquelle sein soll
DCO
LFXT1 im NF- oder HF-Modus
XT2
und entsprechend die Register BCSCTL1 und BCSCTL2 initialisieren.
Außerdem musst Du auf das Einschwingen des Oszillators warten;
Beispielcode findet sich im User's Manual im Abschnitt 4 ("Basic Clock
Module").
Das ist ja schön und gut, aber bevor Du dem Timer_A irgendeinen Takt
zuführst, musst Du den erstmal erzeugen. Auch den Takt, mit dem der
Controller selber läuft, und den Takt, mit dem Du die UART versorgen
willst.
Und dafür ist beim MSP430 das "Basic Clock Module" zuständig, das im
Abschnitt 4 des "User's Manual" beschrieben wird.
Ohne Initialisierung wird ACLK vom LFXT1 im NF-Modus versorgt; hängt da
überhaupt ein Quarz dran?
MCLK und SMCLK hingegen werden vom DCO mit irgendwas um 1 MHz versorgt.
Den Fehler hab ich gefunden, der ADC wurde mit dem falschen Takt
gespeist.
ADC12SSEL_0
Das Taktspiel funktioniert nun tadellos, jedoch machen mir die Werte des
ADC ein wenig sorgen. Ich haben an einen der Eingaenge einen
Funktionsgenerator angeschlossen und die anderen beiden abzutastenden
Kanaele auf Masse gelegt. Ab und zu tauchen extreme Messspitzen auf,
welche foellig aus dem Rahmen fallen. Bei dem Signal handelt es sich um
einen Sinus, 20hz, Amplitude 20mv-1V. Die Fehlmessungen liegen immer
bei Maximalauschlag(3.3V). Mit sample an hold ich auch schon versucht
die Messungen zu verbessern, jedoch ohne Erfolg. Hat jemand eine Idee?
Das bedeutet, daß Du einen Uhrenquarz oder dergleichen an LFXT1
angeschlossen hast und den als Quelle für ACLK verwendest. Das scheinen
bei Dir 32 kHz zu sein, damit versorgst Du sowohl den Timer_A als auch
den Baudratengenerator Deiner UART.
Für MCLK und SMCLK verwendest Du hingegen den DCO. Und den ADC steuerst
Du mit einem weiteren internen Oszillator, dem ADC12OSC an.
Wenn der ADC-Takt, der Prozessortakt und der Timertakt nicht aus einem
gemeinsamen Taktsignal abgeleitet werden, dann kann es zu sehr
"interessanten" Nebeneffekten in Form von Schwebungen auf dem
ADC-Ergebnis kommen. Um saubere Messergebnisse zu erhalten, sollten alle
Takte sich auf einen Referenztakt beziehen. ACLK ist bei Deiner
Anwendung dafür zu langsam, der DCO zu ungenau, vor allem eignet er sich
nicht als Baudratengenerator.
Es gibt zwar eine AppNote von TI, die beschreibt, wie man mit einem
32kHz-ACLK den DCO permanent nachjustieren kann, der resultierende
DCO-Takt ist, gemittelt über alles, auch ausreichend genau. Für eine
ADC-Ansteuerung taugt aber auch das nicht, weil die DCO-Umschaltung
durchaus auch während eines Sample-Vorganges des ADC geschehen kann, was
wieder interessante Nebeneffekte hervorrufen kann.
Um wirklich stabil stehende und saubere Messwerte zu erhalten, sollte
man obendrein eine Netzbrummkompensation vorsehen. Diese funktioniert
so, daß während einer Netzfrequenzperiode (in Europa 20 msec) in
gleichmäßigen Abständen mehrere Messungen durchgeführt werden und
deren Mittelwert gebildet wird.
So erhält man bei halbwegs sauberen Schaltungsdesign (Layout,
Entkopplungskondensatoren etc.) ein bis aufs letzte Bit ruhig stehendes
ADC-Ergebnis.
Die hierfür erforderliche Takterzeugung lässt sich am einfachsten mit
einem 8MHz-Quarz an XT2 oder LFXT1 aufbauen.
Wird LFXT1 im HF-Modus verwendet, dann werden MCLK und ACLK daraus
abgeleitet; SMCLK kann dann nicht verwendet werden.
Wird hingegen XT2 verwendet, werden MCLK und SMCLK daraus abgeleitet;
ACLK kann nicht genutzt werden.
Das macht aber nichts, weil alle Peripheriemodule wahlweise ihren
Referenztakt aus ACLK oder SMCLK beziehen können.
Also wie ich schon ganz am Anfang erwähnte, ist Dein Problem ähnlich
gelagert wie hier:
Beitrag "[MSP430] Probleme mit dem Mikrocontroller"
Wenn auch diesmal in die serielle Datenübertragung verlagert!
Rechne doch mal nach:
Dein Timer_A feuert alle 15,625ms
Dein Timer_B alle 2,93ms (passt locker 4x in Timer_A Intervall -> OK)
ABER:
Pro Timer_B Intervall werden 3 Bytes per UART versendet. Wenn ich
richtig rechne, dauert eine Datenübertragung (1 Start, 8 Daten, 1 Stop,
9600bd) 1,042ms. das ganze 3x macht 3,125ms! Du hast pro
Timer_B-Intervall aber nur 2,93ms zur Verfügung, d.h. Dein Timing
überholt sich irgendwann selbst und führt zu undefinierten Zuständen!
Und dabei sind ADC-Wandlungszeit und Mittelwertbildung noch gar nicht
mit eingerechnet!