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").
Ich habe den Timer A wie folgt intialisiert:
1 | TACTL = TASSEL_1 | ID_0; //SourceClock = ACLK |
damit habe ich ACLK als Clock gewaehlt.
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?
Nein, den Fehler hast Du nach wie vor nicht gefunden. Oder initialisierst Du mittlerweile die Register des "Basic Clock Module"?
doch, DCOCTL = DCO0 + DCO1 + DCO2; BCSCTL1 = RSEL0 + RSEL1 + RSEL2; BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0; ok so?
Damit stellst du den DCO auf irgendeine Frequenz ein, die wohl bei etwa 5MHz liegen könnte.
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!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.