mikrocontroller.net

Forum: Compiler & IDEs Low-Frequency-Clk MSP430


Autor: Jan Stumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

ich versuche z.Z. verzweifelt einen MSP430 mit einem 32khz Uhrenquarz
zum Laufen zu bewegen (MSP430F1121). Ich hab, wie im Datenbaltt
beschrieben nur den Quarz an XIN/XOUT angeschlossen und verwende
folgenden Init-Code :

void vClockInit( void ){
     WDTCTL = WDTPW + WDTHOLD;     /* Watchdog deaktivieren */
     BCSCTL1 &=  ~0x30;//select low-frequencymode, ACKL-Divider = 1
     BCSCTL2 = 0xC8;               /* set MCLK=ACLK*/
     }

kommt ursprünglich aus der c't. Laut Datenblatt ist beim LF-Mode ja
das abfragen des Errorbits nicht nötig, oder? Am Oszi bekomm ich zwar
ein 32 khz Signal, daß allerdings nur eine Amplitude von 360mV hat (um
2.5V herum, bei 3.6V VCC). Das ist doch nicht normal, oder? Hat jemand
vieleicht ein Codesample zur Initialisierung des Clks für den mspgcc
bei 32Khz? Oder hat jemand ne Idee, was ich falsch mache?

Vielen Dank am Voraus

Jan Stumpf

Autor: Jörg Zastrau (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MSP430 LF-XTAL,

ich fange gerade mit dem MSP430 an und bin gestern gleich
bei der Programmierung der ersten paar Zeilen auf das gleiche
Problem gestossen.

Ich benötige den Watchdog ebenfalls im Interval-Mode, um den
DSO zu synchronisieren, da TimerA für komplett für andere Zwecke
benötigt wird.

MSP430F1232 läuft mit 3,4V, zweilagiger Platinenaufbau. Uhren-
quarz schwang nicht.

Erster Augenschein:
- Der super-duper Billigquarz tut nicht (möglicherweise auch
  zu lange gelötet) trotz passender Spezifikation.
- Anderer Quarz mit 2 * 3pF parallel tuts... den im Datenblatt
  empfohlenen 5,1MOhm-Widerstand habe ich mir verkniffen, da
  VDD>2,5V.
- Dummerweise habe ich mich verlayoutet und auf der Rückseite
  der XIN/XOUT-Pins sind ein Eingang und der korrespondierende
  Ausgang eines derzeit noch unbeschalteten OPs angeordnet (schwingt
  natürlich) Möglicherweise gibt es dort einen Einfluß.
  Das wurde im Layout jetzt berücksichtigt, so daß auch der
  gegenüberliegenden Seite beim nächsten Mal Masseflächen
  vorhanden sind, so wie es sein sollte.

Fazit: Aufpassen beim Layout, brav Ground-Traces legen und schön
       Abstand halten von anderen Leitungen.

Jetzt noch eine Beobachtung zum MSP-GCC und Watchdog (derzeit noch
XY-ungelöst):

- Der DSO schwingt sofort an, beim Umschalten des Watchdog auf
  LFOSC als Taktgeber muß erst eine Weile gewartet werden.
  Code-Snipped vom anderen Thread hier (TI-Code):

  do {
        IFG1 &= ~=OFIFG           // Clear OSC-Fault Flag
        for (i=0xff; i>0; i--);   // settle time
  } while (IFG1 & 0FIFG);         // OSC-Fault?

- GDB schmiert ab beim Verwendung von ACLK beim Watchdog, beim
  Verwendung des DSO klappt es -> möglicherweise läuft die LFCLK
  durch und erzeugt mehrere Interrupts während eines Steps, was
  den JTAG durcheinanderbringt oder GDB verwendet selbst diese
  Methode, um SW-Breakpoints zu setzten (weis jemand Rat?)
  Stand-alone funzt es aber.

- Man kann bei den meisten MSPs einen IO-Pin dazu verurteilen,
  die ACLK gebuffert auszugeben, bei mir wäre das glaube ich P2.0,
  wenn dort nicht was dranhängen würde.

zu Deinem Problem:

  Der Watchdog muss natürlich auch wieder eingeschaltet werden,
  sprich WDTHOLD darf beim nächsten Befehl nicht gesetzt sein.


73, Jörg

Autor: Jörg Zastrau (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Self-Re

Du hast natürlich recht... Im LF-Mode scheint das Error-Flag
nicht gesetzt zu werden (slaa081.pdf)

Jörg

Autor: Jan Stumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Jörg!

>Erster Augenschein:
>- Der super-duper Billigquarz tut nicht (möglicherweise auch
>  zu lange gelötet) trotz passender Spezifikation.
hmm, vieleicht ist meiner auch nicht gut genug. Ich hatte nur bisher
keine Probleme mit Quarzen.

>- Anderer Quarz mit 2 * 3pF parallel tuts... den im Datenblatt
>  empfohlenen 5,1MOhm-Widerstand habe ich mir verkniffen, da
>  VDD>2,5V.
das werde ich mal ausprobieren.

>- Dummerweise habe ich mich verlayoutet und auf der Rückseite
>  der XIN/XOUT-Pins sind ein Eingang und der korrespondierende
>  Ausgang eines derzeit noch unbeschalteten OPs angeordnet (schwingt
>  natürlich) Möglicherweise gibt es dort einen Einfluß.
>  Das wurde im Layout jetzt berücksichtigt, so daß auch der
>  gegenüberliegenden Seite beim nächsten Mal Masseflächen
>  vorhanden sind, so wie es sein sollte.
also wenn das mit 32khz nicht funktioniert, ist das doch schon ein
ziemlicher Nachteil des MSP430. ich achte bei meinen designs auch immer
auf EMV, aber sowas muss bei 32khz schon möglich sein.

>zu Deinem Problem:
> Der Watchdog muss natürlich auch wieder eingeschaltet werden,
> sprich WDTHOLD darf beim nächsten Befehl nicht gesetzt sein.
aha, da könnte mein fehler noch liegen.

Könntest du deinen Initcode mal posten? Wäre super!

danke

Jan

Autor: Jörg Zastrau (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi Jan,

die ersten Schritte mit dem MSP430 sind gemacht und das "Gerippe"
für meine Applikation steht.

Ich brauche eine relativ hohe quarzstabile Frequenz.
Der Timer A ist durch eine PWM komplett belegt, d.h.
ich muß auf den WDT-Timer im Intervall-Modus zurückgreifen.

Statt einer FLL habe ich jedoch in Anlehnung an SLAA074 eine
PLL gebastelt. Da diese bei mir alle 24kHz einrasten kann ist
zunächst eine schnelle Auswahl des benötigten Frequenzbereichs
nötig.

Das Programmlauf sieht derzeit wie folgt aus:

- Auf den LFXTCLK warten mittel TimerA, da kein OSC-Fault
  generiert wird. Dauert bei mir ca. 200ms! (Billigquarz)
- Der WDT wird nun mit ACLK gespeist mit einer Periode von
  ca. 15ms. Timer A zählt nun DCO-Zyklen.
- Die RSEl-Einstellungen werden (mit DCOCTL=0) so lange
  ausgehend vom Maximalwert verringert, bis eine zu geringe
  Frequenz ermittelt wird.
- Danach kann es nur noch aufwärts gehen und eine passende
  Einstellung von DCOx und MODx wird mit successiver
  Approximation wiederum unter Verwendung von TMRA und des
  WDT ermittelt.

- Danach geht die Kontrolle an die PLL über. Es wird dabei
  jeweils nur ein Frequenzschritt gemacht.

Frage: Weiss jemand, ob die einzelnen RSel-Bereiche sich
überlappen? Und wenn ja, was sind die passenden DCOCTL-
Einstellungen?

zum langsamen Anschwingen des Quarzes: bei mir ist das Ding
jetzt stabil. Und Du willst doch auch "Low Power", oder?

sorry, daß noch keine vernünftige Dokumentation vorhanden ist.
Der Code kann sicherlich auch noch deutlich verbessert werden
hinsichtlich der Größe, für mich reichts aber erstmal.

Schreib kurz, wenn Du Fragen hast...

Achja.. ist für GCC.

bis dann, Jörg

Autor: m@is (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe auch ein Problem mit meinem 32kHz Quarz. Er schwingt mit
relativ kleiner Amplitudenänderung, aber korrekter Frequenz. Ich habe
ihn mit und ohne zusätzliche Kondensatoren angeschlossen (der MSP hat
ja schon intern 12pF).
Ich arbeite mit dem MSP430F1232, nutze den DCO bei max. Frequenz für
MCLK und möchte den 32kHz für ACLK und zum synchronosieren nutzen.

Den Schnippsel habe ich aus einem TI Beispiel.

BCSCTL1 &= ~OSCOFF;

  do {
      IFG1 &= ~OFIFG;
      for (w = 0xff; w>0; w--);
      }
  while ((IFG1 & OFIFG) != 0);


  BCSCTL2 = 0x88;

Leider komme ich nicht weiter, MSP verlässt die Schleife nicht.

Gruß m@is

Autor: Jörg Zastrau (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

> Ich arbeite mit dem MSP430F1232, nutze den DCO bei max.
> Frequenz für MCLK und möchte den 32kHz für ACLK und
> zum synchronosieren nutzen.

> Den Schnippsel habe ich aus einem TI Beispiel.

> BCSCTL1 &= ~OSCOFF;

meiner Meinung nach ist OSCOFF-Flag im Status Register
und dient zur Einstellung des Low-Power modes (LPM4).
An der Stelle im BCSCTL1 steht das höherwertige Bit des
ACLK-Vorteilers (DIVA1), den Du hiermit löscht und den Teiler
damit in Abhängigkeit von DIVA0 auf /1 oder /2 einstellst.

>  do {
>      IFG1 &= ~OFIFG;
>      for (w = 0xff; w>0; w--);
>      }
>  while ((IFG1 & OFIFG) != 0);

bin ich auch zunächst drauf reingefallen. Da Du den 32kHz-Quarz
verwendest wird der Oszillator im LFXT-Modus betrieben. Das
Oszillator-Fault-Interrupt-Flag wird in diesem Modus nicht gesetzt,
d.h. die CPU wartet sich einen Ast...


>  BCSCTL2 = 0x88;

Hiermit wird auf XT2 (nicht präsent) für MCLK und SMCLK umgeschaltet.
Die Zeile kannst Du rauswerfen, da diese Clocks defaultmäßig mit dem
internen DCO laufen.

Ich benutzt Timer A, um auf den LFXT-Quarz zu warten...

Meine defines sind:
#define DCO_FREQ  2457600
#define TAR_TICKS  (DCO_FREQ/64)   // with WDT: 38,4kHz/8192
#define DCO_SETTLE  20              // settle time for DCO
#define LFXT_RETRY  40000
#define WDTCTL_INIT  WDTPW|WDTCNTCL|WDTTMSEL|WDTIS1|WDTSSEL
#define BCSCTL1_INIT  XT2OFF|RSEL2|RSEL1|RSEL0

die Funktion die(xxx) blinkt xxx mal mit einer Leuchtdiode und
hält die CPU bei Fehlern an.

Momentan sieht mein Code so aus:

[..schnipp..]

u16 retry=LFXT_RETRY;                   // retry counter

// wait for LFXT1CLK using Timer A
TACTL = TASSEL0+MC1+TACLR;              // start timer A using ACLK,
                                        // clear Interrupt flag
WDTCTL = WDTPW|WDTCNTCL|WDTHOLD;        // clear and stop
                                        // watchdogbefore interval
                                        // change

do { retry--;                           // ACLK works if timer
                                        // starts counting; loop
                                        // ~10cycles
} while ((TAR<4096)&&retry);            // wait some clock cycles
                                        // or retry

if (!retry)                             // timer A not working
                                        // -> die with postcode 4;
        die(PNOXT);                     // blink LED 8-)

[...schnapp...]


und dann weiter um den DCO auf eine definierte Startfrequenz
zu stellen (laufende Synchronisation noch nicht fertig... aber
Du kannst den Code aus SLAA074 nehmen, wenn Du Timer A frei hast):

[...schnipp...]

// since we have now a stable ACLK change
// the WDT timer with 15,625ms period in
// interval mode and use timer A in continous
// mode to adjust DCO frequency.

DCOCTL = 0x00;
BCSCTL1 = BCSCTL1_INIT;                 // choose high frequency
                                        // range

retry = 8;
signed int adjust;
do {  retry--;
  if ((adjust=wdt_poll(DCO_SETTLE))<0)  // timer A too fast?
      BCSCTL1 -=1;                      // yes -> decrease RSEL
                                        // value
} while ((adjust<0)&&retry);            // until DCO frequency
                                        // too low

if (!retry)                             // R-Selection failed
        die(PNOPLL);

// successive approximation for DCOCTL
int i;
   for (i=15; i>=0;i--) {               // process DCOx and MODx
                                        // Bits
      adjust = wdt_poll(DCO_SETTLE>>1);
      DCOCTL |= (1<<i);                 // try setting a higher
                                        // frequency
      if (adjust<0) {                   // too fast?
           DCOCTL &= ~(1<<(i+1));       // undo last frequency change
      }
}

[...schnapp...]

was noch fehlt ist die Routine wdt_poll... diese hier
ist für GCC (aufpassen mit TABs):

[...schnipp...]

int
wdt_poll(u16 t_settle)
{

int adjust = 0;

NOP_WAIT(t_settle);                     // stabilize clock

// well well, gcc is too clever..
// force setting of TACTL(0x160) and WDTCTL(0x120) using
// registers in a timely manner
// force fast polling of WDT_Flag and capture of Timer A (0x170)

 asm    ("   mov   %[wdc],   &0x120   \n\t"\
         "   mov   %[tac],   &0x160   \n\t"\
         "   bic   #1,       &0x002   \n\t"\
         "   mov   %[tic],   %[adj]   \n\t"\
         "1: bit.b #1,       &0x002   \n\t"\
         "   jz    1b                 \n\t"\
         "   sub   &0x170,   %[adj]   \n\t"\
         : [adj] "=r" (adjust)\
         : [wdc] "i" (WDTCTL_INIT),
[tac]"r"(TACLR+TASSEL1+MC1+ID0),[tic] "i" (TAR_TICKS>>1));

return adjust;
}


[...schnapp...]

danach kann man Timer A wieder benutzen... WDT ist natürlich
auch verkonfiguriert. Den DCO sollte mann gelegentlich wieder
nachstellen... bin da aber noch dran. Achja, das "r" für [tac]
ist kein Fehler...

der Code oben funktioniert (im Gegensatz zu meinem vorherigen
Posting 8-)) und ist getestet auf MSP430F1232...

schreib mal, ob's geklappt hat oder wenn ich was vergessen haben
sollte...

73,

Jörg

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.