MSP430 32kHz Quarz / Crystal

32khz_02Vor ein paar Tagen habe ich einmal den mitgelieferten Quarz (Launchpad, MS3V-T1R) getestet und ein paar Messungen durchgeführt. Weiterhin wurde ein 32kHz Uhrenquarz von Pollin getestet (CFS-206). Eine kurze Einführung für die Benutzung eines 32kHz Quarz und die Initialisierung für den MSP430.

 

 

Wer es sich nicht zutraut den mitgelieferten Quarz auf das Launchpad zu löten, dem empfehle ich den Quarz von Pollin. Dieser lässt sich einfach an die Stiftleiste löten, oder per Buchsen anschließen. Der MSP430(G) hat zwei interene Ladekapazitäten CL1 und CL2, die per Software ausgewählt werden können (BSCTL3 Register -> ~1pF bis 12.5pF, siehe User-Guide). Es können aber auch externe Kondensatoren angeschlossen werden, falls nötig.

Daten mitgelieferter Quarz:

MS3V-T1R (32.768kHz)
Load Capacitance: 12.5pF
Frequency Tolerance:+/-20ppm (ppm=parts per million)
SMD Metal Package
Datasheet

32khz_01 32khz_02

Daten Uhrenquarz von Pollin:

CFS-206 (32.768 kHz)
Load Capacitance: 12,5 pF
Frequency Tolerance: +/-20ppm
Datasheet

32khz_uhr

(Diese Methode funktioniert zwar, ist aber nicht zu empfehlen, der Quarz muss so nah wie möglich am Controller gelötet werden)

Quarz Initialisierung

Wer sich näher mit der Thematik beschäftigen will, findet im UserGuide ab Seite 273 alle nötigen Informationen.

  1. BCSCTL3|=XCAP_3;
  2.  
  3. do
  4. {
  5.     IFG1&=~OFIFG;
  6.     __delay_cycles(1000);
  7. }
  8. while(IFG1&OFIFG);
BCSCTL3|=XCAP_3;

do
{
    IFG1&=~OFIFG;
    __delay_cycles(1000);
}
while(IFG1&OFIFG);

In der ersten Zeile werden Einstellungen am BCSCTL3 Register (Basic Clock System Control Register 3) vorgenommen. Hier können die Frequenzen und Ladekapazitäten ausgewählt werden. In diesem Fall reicht es Bit 3-2 -> XCAP_3 (~12.5pF) zu setzen. XT2Sx (00 = 0.4 bis 1MHz) und LFXT1Sx (00 = 32768Hz LFXT1) sind standardmäßig nicht gesetzt. Im BCSCTL1 (Basic Clock System Control Register 1) ist standardmäßig das Bit XTS (0 = Low-frequency mode) nicht gesetzt. In diesem Register kann noch ein Vorteiler für ACLK ausgewählt werden (1,2,4,8), in diesem Fall werden die Bits DIVAx nicht gesetzt (00 = /1).

In der do-while Schleife wird zuerst das OFIFG (Oscillator fault interrupt flag) Bit im IFG1 Register (Interrupt Flag Register 1) auf 0 gesetzt (no interrupt pending). Danach wird 1000 Zyklen gewartet (Einschwingzeit, sollte vielleicht höher sein ~10ms) und geprüft ob das OFIFG Bit immer noch gesetzt ist. Falls ja, wird nochmal gewartet.

Timer-Initialisierung

Als CLK-Source für den TImer soll der 32kHz Quarz dienen.

TACTL|=TASSEL_1+ID_0; //ACLK, 1x divider

Im TACTL Register werden die Bits TASSEL_1 (01 = ACLK) gesetzt und der Vorteiler bleibt auf “/1” (nicht nötig ID_0 zu schreiben). In diesem Fall entsprechen 32768 Zyklen genau eine Sekunde ( (32768Hz*1,0s)/1=32768).

Messung

Im Test-Programm blinkt eine LED mit 2Hz (250ms ON, 250ms OFF => T=500ms => f=2Hz). Benutzt wurde der mitgelieferte Quarz (SMD Metal Package).

Auto-Measurement (P1.6, LED)

32khz_auto

Manuell (P1.6, LED)

32khz_manuell

Auto-Measurement (ACLK, P1.0)

32khz_aclk

C-Programm

FILE: main.c

  1. /*************************************************
  2.  *     ___       _             _    
  3.  *    |   |_ _ _| |___ ___   _| |___
  4.  *    | | |_'_| . | -_|  _|_| . | -_|
  5.  *    |___|_,_|___|___|___|_|___|___|
  6.  *
  7.  * FILE:     main.c
  8.  * Author:   declis (xdec.de)
  9.  ************************************************/
  10.  
  11. #include <msp430g2231.h>
  12. #include "timer.h"
  13.  
  14. void main(void)
  15. {
  16.     WDTCTL=WDTPW+WDTHOLD;       // stop watchdog timer
  17.     BCSCTL1=CALBC1_1MHZ;
  18.     DCOCTL=CALDCO_1MHZ;
  19.     BCSCTL3|=XCAP_3;
  20.  
  21.     do
  22.     {
  23.         IFG1&=~OFIFG;
  24.         __delay_cycles(1000);
  25.     }
  26.     while(IFG1&OFIFG);
  27.  
  28.     P1DIR|=BIT6;                //P1.6 (LED2) -> output
  29.     P1OUT&=~BIT6;               //clear P1.6 (LED2 off)
  30.     P1SEL|=BIT0;                //ACLK on P1.0
  31.     P1DIR|=BIT0;
  32.  
  33.     init_TimerA();              //initialize TimerA
  34.     _EINT();                    //enable interrupt
  35.  
  36.     while(1);
  37. }
/*************************************************
 *     ___       _             _     
 *    |   |_ _ _| |___ ___   _| |___
 *    | | |_'_| . | -_|  _|_| . | -_|
 *    |___|_,_|___|___|___|_|___|___|
 *
 * FILE:     main.c
 * Author:   declis (xdec.de)
 ************************************************/

#include <msp430g2231.h>
#include "timer.h"

void main(void)
{
    WDTCTL=WDTPW+WDTHOLD;       // stop watchdog timer
    BCSCTL1=CALBC1_1MHZ;
    DCOCTL=CALDCO_1MHZ;
    BCSCTL3|=XCAP_3;

    do
    {
        IFG1&=~OFIFG;
        __delay_cycles(1000);
    }
    while(IFG1&OFIFG);

    P1DIR|=BIT6;                //P1.6 (LED2) -> output
    P1OUT&=~BIT6;               //clear P1.6 (LED2 off)
    P1SEL|=BIT0;                //ACLK on P1.0
    P1DIR|=BIT0;

    init_TimerA();              //initialize TimerA
    _EINT();                    //enable interrupt

    while(1);
}

FILE: timer.c

  1. /*************************************************
  2.  *     ___       _             _    
  3.  *    |   |_ _ _| |___ ___   _| |___
  4.  *    | | |_'_| . | -_|  _|_| . | -_|
  5.  *    |___|_,_|___|___|___|_|___|___|
  6.  *
  7.  * FILE:     timer.c
  8.  * Author:   declis (xdec.de)
  9.  ************************************************/
  10.  
  11. #include <msp430g2231.h>
  12. #include "timer.h"
  13.  
  14. #define cycles 8192         // 250ms ACLK=32kHz Quarz
  15. //#define cycles 31250      // 250ms SMCLK=1MHz
  16.  
  17. /* cycles=(seconds*Frequency_Hz)/divider */
  18. /* seconds=(divider*cycles)/Frequency_Hz  */
  19. void init_TimerA(void)
  20. {
  21.     TACTL|=TASSEL_1+ID_0;   // ACLK, 1x divider
  22.     //TACTL|=TASSEL_2+ID_3; // SMCLK, 8x divider
  23.     TACCR0=cycles;
  24.     TACCTL0|=CCIE;          // enable TimerA interrupt
  25.     TACTL|=MC_1;            // start timer in up-mode
  26. }
  27.  
  28. /* Timer_A ISR */
  29. #pragma INTERRUPT (ISR_TimerA);
  30. #pragma vector=TIMERA0_VECTOR
  31. void ISR_TimerA(void)
  32. {
  33.     P1OUT^=BIT6;        // toggle P1.6
  34. }
/*************************************************
 *     ___       _             _     
 *    |   |_ _ _| |___ ___   _| |___
 *    | | |_'_| . | -_|  _|_| . | -_|
 *    |___|_,_|___|___|___|_|___|___|
 *
 * FILE:     timer.c
 * Author:   declis (xdec.de)
 ************************************************/

#include <msp430g2231.h>
#include "timer.h"

#define cycles 8192         // 250ms ACLK=32kHz Quarz
//#define cycles 31250      // 250ms SMCLK=1MHz

/* cycles=(seconds*Frequency_Hz)/divider */
/* seconds=(divider*cycles)/Frequency_Hz  */
void init_TimerA(void)
{
    TACTL|=TASSEL_1+ID_0;   // ACLK, 1x divider
    //TACTL|=TASSEL_2+ID_3; // SMCLK, 8x divider
    TACCR0=cycles;
    TACCTL0|=CCIE;          // enable TimerA interrupt
    TACTL|=MC_1;            // start timer in up-mode
}

/* Timer_A ISR */
#pragma INTERRUPT (ISR_TimerA);
#pragma vector=TIMERA0_VECTOR
void ISR_TimerA(void)
{
    P1OUT^=BIT6;        // toggle P1.6
}

FILE: timer.h

  1. /*************************************************
  2.  *     ___       _             _    
  3.  *    |   |_ _ _| |___ ___   _| |___
  4.  *    | | |_'_| . | -_|  _|_| . | -_|
  5.  *    |___|_,_|___|___|___|_|___|___|
  6.  *
  7.  * FILE:     timer.h
  8.  * Author:   declis (xdec.de)
  9.  ************************************************/
  10.  
  11. #ifndef TIMER_H_
  12. #define TIMER_H_
  13.  
  14. void init_TimerA(void);
  15.  
  16. #endif /*TIMER_H_*/
/*************************************************
 *     ___       _             _     
 *    |   |_ _ _| |___ ___   _| |___
 *    | | |_'_| . | -_|  _|_| . | -_|
 *    |___|_,_|___|___|___|_|___|___|
 *
 * FILE:     timer.h
 * Author:   declis (xdec.de)
 ************************************************/

#ifndef TIMER_H_
#define TIMER_H_

void init_TimerA(void);

#endif /*TIMER_H_*/

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.