This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

使用TI官方提供的DCO校准程序,结果输出频率仍然误差很大

Other Parts Discussed in Thread: MSP430G2231, MSP430F2131

使用了如下程序,结果SMCLK的输出非常奇怪,根本就不是方波

//******************************************************************************
// MSP430G2xx1 Demo - DCO Calibration Constants Programmer
//
// NOTE: THIS CODE REPLACES THE TI FACTORY-PROGRAMMED DCO CALIBRATION
// CONSTANTS LOCATED IN INFOA WITH NEW VALUES. USE ONLY IF THE ORIGINAL
// CONSTANTS ACCIDENTALLY GOT CORRUPTED OR ERASED.
//
// Description: This code re-programs the G2xx1 DCO calibration constants.
// A software FLL mechanism is used to set the DCO based on an external
// 32kHz reference clock. After each calibration, the values from the
// clock system are read out and stored in a temporary variable. The final
// frequency the DCO is set to is 1MHz, and this frequency is also used
// during Flash programming of the constants. The program end is indicated
// by the blinking LED.
// ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO
// //* External watch crystal installed on XIN XOUT is required for ACLK *//
//
// MSP430G2xx1
// ---------------
// /|\| XIN|-
// | | | 32kHz
// --|RST XOUT|-
// | |
// | P1.0|--> LED
// | P1.4|--> SMLCK = target DCO
//
// A. Dannenberg
// Texas Instruments Inc.
// May 2010
// Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 3.42A
//******************************************************************************
#include "msp430g2231.h"

#define DELTA_1MHZ 244 // 244 x 4096Hz = 999.4Hz
#define DELTA_8MHZ 1953 // 1953 x 4096Hz = 7.99MHz
#define DELTA_12MHZ 2930 // 2930 x 4096Hz = 12.00MHz
#define DELTA_16MHZ 3906 // 3906 x 4096Hz = 15.99MHz

unsigned char CAL_DATA[8]; // Temp. storage for constants
volatile unsigned int i;
int j;
char *Flash_ptrA; // Segment A pointer
void Set_DCO(unsigned int Delta);

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
for (i = 0; i < 0xfffe; i++); // Delay for XTAL stabilization
P1OUT = 0x00; // Clear P1 output latches
P1SEL = 0x10; // P1.4 SMCLK output
P1DIR = 0x11; // P1.0,4 output

j = 0; // Reset pointer

Set_DCO(DELTA_16MHZ); // Set DCO and obtain constants
CAL_DATA[j++] = DCOCTL;
CAL_DATA[j++] = BCSCTL1;

Set_DCO(DELTA_12MHZ); // Set DCO and obtain constants
CAL_DATA[j++] = DCOCTL;
CAL_DATA[j++] = BCSCTL1;

Set_DCO(DELTA_8MHZ); // Set DCO and obtain constants
CAL_DATA[j++] = DCOCTL;
CAL_DATA[j++] = BCSCTL1;

Set_DCO(DELTA_1MHZ); // Set DCO and obtain constants
CAL_DATA[j++] = DCOCTL;
CAL_DATA[j++] = BCSCTL1;

Flash_ptrA = (char *)0x10C0; // Point to beginning of seg A
FCTL2 = FWKEY + FSSEL0 + FN1; // MCLK/3 for Flash Timing Generator
FCTL1 = FWKEY + ERASE; // Set Erase bit
FCTL3 = FWKEY + LOCKA; // Clear LOCK & LOCKA bits
*Flash_ptrA = 0x00; // Dummy write to erase Flash seg A
FCTL1 = FWKEY + WRT; // Set WRT bit for write operation
Flash_ptrA = (char *)0x10F8; // Point to beginning of cal consts
for (j = 0; j < 8; j++)
*Flash_ptrA++ = CAL_DATA[j]; // re-flash DCO calibration data
FCTL1 = FWKEY; // Clear WRT bit
FCTL3 = FWKEY + LOCKA + LOCK; // Set LOCK & LOCKA bit

while (1)
{
P1OUT ^= 0x01; // Toggle LED
for (i = 0; i < 0x4000; i++); // SW Delay
}
}

void Set_DCO(unsigned int Delta) // Set DCO to selected frequency
{
unsigned int Compare, Oldcapture = 0;

BCSCTL1 |= DIVA_3; // ACLK = LFXT1CLK/8
TACCTL0 = CM_1 + CCIS_1 + CAP; // CAP, ACLK
TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, cont-mode, clear

while (1)
{
while (!(CCIFG & TACCTL0)); // Wait until capture occured
TACCTL0 &= ~CCIFG; // Capture occured, clear flag
Compare = TACCR0; // Get current captured SMCLK
Compare = Compare - Oldcapture; // SMCLK difference
Oldcapture = TACCR0; // Save current captured SMCLK

if (Delta == Compare)
break; // If equal, leave "while(1)"
else if (Delta < Compare)
{
DCOCTL--; // DCO is too fast, slow it down
if (DCOCTL == 0xFF) // Did DCO roll under?
if (BCSCTL1 & 0x0f)
BCSCTL1--; // Select lower RSEL
}
else
{
DCOCTL++; // DCO is too slow, speed it up
if (DCOCTL == 0x00) // Did DCO roll over?
if ((BCSCTL1 & 0x0f) != 0x0f)
BCSCTL1++; // Sel higher RSEL
}
}
TACCTL0 = 0; // Stop TACCR0
TACTL = 0; // Stop Timer_A
BCSCTL1 &= ~DIVA_3; // ACLK = LFXT1CLK
}

  • 建议您使用下面的程序测试一下

    /* --COPYRIGHT--,BSD_EX
     * Copyright (c) 2012, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     *******************************************************************************
     * 
     *                       MSP430 CODE EXAMPLE DISCLAIMER
     *
     * MSP430 code examples are self-contained low-level programs that typically
     * demonstrate a single peripheral function or device feature in a highly
     * concise manner. For this the code may rely on the device's power-on default
     * register values and settings such as the clock configuration and care must
     * be taken when combining code from several examples to avoid potential side
     * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
     * for an API functional library-approach to peripheral configuration.
     *
     * --/COPYRIGHT--*/
    //******************************************************************************
    //  MSP430G2xx1 Demo - Basic Clock, Output Buffered clocks with preloaded DCO
    //                     calibration constants for BCSCTL1 and DCOCTL.
    //  
    //  Description: Buffer ACLK on P1.0, default SMCLK(DCO) on P1.4 and MCLK/10 on
    //  P1.1. DCO is software selectable to 1, 8, 12, or 16Mhz using calibration
    //  contstants in INFOA.
    //
    //  ACLK = LFXT1 = 32768, MCLK = SMCLK = Selectable at 1, 8, 12 or 16Mhz
    //  //* External watch crystal installed on XIN XOUT is required for ACLK *//	
    //	//* By default, the MSP430 uses XT1 to source ACLK; P2.6/7 configured 
    //  //* automatically.
    //               MSP430G2xx1
    //             -----------------
    //         /|\|         P2.6/XIN|-
    //          | |                 | 32kHz
    //          --|RST     P2.7/XOUT|-
    //            |                 |
    //            |       P1.4/SMCLK|-->SMCLK = Default DCO
    //            |             P1.1|-->MCLK/10 = DCO/10
    //            |        P1.0/ACLK|-->ACLK = 32kHz
    // 
    //  D. Dang
    //  Texas Instruments Inc.
    //  October 2010
    //  Built with IAR Embedded Workbench Version: 3.42A
    //******************************************************************************
    
    #include <msp430.h>
    
    int main(void)
    {
      WDTCTL = WDTPW +WDTHOLD;                  // Stop Watchdog Timer
    
     //1Mhz
        if (CALBC1_1MHZ==0xFF)					// If calibration constants erased
      {											
        while(1);                               // do not load, trap CPU!!	
      }
      DCOCTL = 0;                               // Select lowest DCOx and MODx settings
      BCSCTL1 = CALBC1_1MHZ;                    // Set range
      DCOCTL = CALDCO_1MHZ;                     // Set DCO step + modulation */
    
    /* //8Mhz
      if (CALBC1_8MHZ==0xFF)					// If calibration constants erased
      {											
        while(1);                               // do not load, trap CPU!!	
      }
      DCOCTL = 0;                               // Select lowest DCOx and MODx settings
      BCSCTL1 = CALBC1_8MHZ;                    // Set range
      DCOCTL = CALDCO_8MHZ;                     // Set DCO step + modulation */
    
    /* //12Mhz
      if (CALBC1_12MHZ==0xFF)					// If calibration constants erased
      {											
        while(1);                               // do not load, trap CPU!!	
      }
      DCOCTL = 0;                               // Select lowest DCOx and MODx settings
      BCSCTL1 = CALBC1_12MHZ;                   // Set range
      DCOCTL = CALDCO_12MHZ;                    // Set DCO step + modulation*/
    
    /* //16Mhz
      if (CALBC1_16MHZ==0xFF)					// If calibration constants erased
      {											
        while(1);                               // do not load, trap CPU!!	
      }
      DCOCTL = 0;                               // Select lowest DCOx and MODx settings
      BCSCTL1 = CALBC1_16MHZ;                   // Set range
      DCOCTL = CALDCO_16MHZ;                    // Set DCO step + modulation*/
    
      P1DIR |= 0x13;                            // P1.0,1 and P1.4 outputs
      P1SEL |= 0x11;                            // P1.0,4 ACLK, SMCLK output
    
      while(1)
      {
        P1OUT |= 0x02;    	                    // P1.1 = 1
        P1OUT &= ~0x02;                         // P1.1 = 0
      }
    }
    
    

  • 我使用的芯片是MSP430F2131,我查看芯片手册,发现该芯片没有XT2时钟源,而使用高频时钟只能采用DCOCLK。
    我需要一个12M的时钟源,但是出厂的DCOCLK精度达不到我们的要求,因此我们需要对DCOCLK校准,然而主时钟也得用DCOCLK,所以好像达不到预期的效果,请问这种情况我们还可以采取什么手段来校准DCO时钟呢
  • 我们继续在下面的链接中讨论
    e2echina.ti.com/.../192782