51/AVR单片机技术驿站!  <在线翻译>     便利工具    特色网址   无弹窗、无插件的绿色站点...  英才招聘   学历查询  喜欢>>收藏我站 

当前位置:首页 > 单片机技术文章 > MSP430单片机 > 详细内容
MSP43021x1时钟校准
发布时间:2009/7/27  阅读次数:1189  字体大小: 【】 【】【
//******************************************************************************
// MSP430x21x1 Demo - Basic Clock, Implement Auto RSEL SW FLL
//
// Description: Set DCO clock to (Delta)*(4096) using software FLL. DCO clock
// is output on P1.4 as SMCLK. DCO clock, which is the selected SMCLK source
// for Timer_A is integrated over LFXT1/8 (4096) until SMCLK is is equal
// to Delta. CCR2 captures ACLK. To use, Set_DCO Timer_A must be
// operating in continuous mode. Watch crystal for ACLK is required for
// this example. Delta must be kept in a range that allows possible
// DCO speeds. Minimum Delta must ensure that Set_DCO loop can complete
// within capture interval. Maximum delta can be calculated be
// f(DCOx7) / 4096. f(DCOx7) can be found in device specific datasheet.
// ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO
// [] To measure SMCLK on P1.4 with the FET, use "Release JTAG on Go"
// in the debugger to have access to the port. Then run the code.
// //* External watch crystal installed on XIN XOUT is required for ACLK *//
/ H. Grewal / A. Dannenberg
// Texas Instruments Inc.
// June 2005
// Built with IAR Embedded Workbench Version: 3.30A
//******************************************************************************
//******************************************************************************

// MSP43021x1时钟校准,21x1出厂时,在Info Flash保存了四种时钟的调整参数
// 分别是 1MHz,8MHz,12MHz,16MHz
// 由于用户在下载程序的时候,会将Info Flash擦除,或芯片出厂校准参数不正确
// 就需要用户自己校准时钟。
// 有两种方法可以校准系统时钟,1;在用户程序初始化时校准,
// 2: 单独运行校准程序,将校准参数保存到InfoFlash
// 中,用户程序直接调用。由于21X1系列的内部时钟
// 精度在整个温度范围内已经达到了2.5%,因此可以
// 用这种方法,减少应用程序占用Flash。
// 要保证CPU供电在3。3V以上
//
// 毛武斌
// 杭州冰河奥特使电子有限公司
// 2006.3.23
// 本程序由TI的例子程序修改而来,使用IAREW430 V3。40A
//******************************************************************************


#include <msp430x21x1.h>

#define DELTA_1M 245
#define DELTA_8M 1954
#define DELTA_12M 2930
#define DELTA_16M 3906

char *pInfoFlash_A;
char AdjBCSCTL1_1M;
char AdjpDCOCTL_1M;
char AdjBCSCTL1_8M;
char AdjpDCOCTL_8M;
char AdjBCSCTL1_12M;
char AdjpDCOCTL_12M;
char AdjBCSCTL1_16M;
char AdjpDCOCTL_16M;
char tmpBCSCTL1;
char tmpDCOCTL;
void Set_DCO (unsigned int delta, char *pBcsctl1_, char *pDcoct_);
void softwareDelay(unsigned int time);
void timeAdelay(unsigned int time);
void main(void)
  {
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    // 测试时钟输出
    P1OUT = 0;
    P1DIR |= BIT3 + BIT4;;       // P1.3,4 output
    P1SEL |= BIT4;                       // P1.4 SMCLK output

  _DINT();
  tmpBCSCTL1 = BCSCTL1;
  tmpDCOCTL = DCOCTL;
  Set_DCO(DELTA_1M, &AdjBCSCTL1_1M, &AdjpDCOCTL_1M);
  Set_DCO(DELTA_8M, &AdjBCSCTL1_8M, &AdjpDCOCTL_8M);
  Set_DCO(DELTA_12M, &AdjBCSCTL1_12M, &AdjpDCOCTL_12M);
  Set_DCO(DELTA_16M, &AdjBCSCTL1_16M, &AdjpDCOCTL_16M);

  BCSCTL1 = tmpBCSCTL1;
  DCOCTL = tmpDCOCTL;
  FCTL2 = FWKEY + FSSEL0 + FN1; // MCLK/3 for Flash Timing Generator
  FCTL1 = FWKEY + ERASE;               // Set Erase bit, allow interrupts
  if(FCTL3 & LOCKA)
    {
      FCTL3 = FWKEY + LOCKA;           // Clear LOCK & LOCKA bits
    }
    pInfoFlash_A = (char *) 0x10C0; // Initialize Flash pointer
    *pInfoFlash_A = 0;                           // Dummy write to erase Flash segment A
    FCTL1 = FWKEY + WRT;                       // Set WRT bit for write operation

  pInfoFlash_A = (char *) CALDCO_16MHZ_; // Initialize Flash pointer
  *pInfoFlash_A++ = AdjpDCOCTL_16M;
  *pInfoFlash_A++ = AdjBCSCTL1_16M;
  *pInfoFlash_A++ = AdjpDCOCTL_12M;
  *pInfoFlash_A++ = AdjBCSCTL1_12M;
  *pInfoFlash_A++ = AdjpDCOCTL_8M;
  *pInfoFlash_A++ = AdjBCSCTL1_8M;
  *pInfoFlash_A++ = AdjpDCOCTL_1M;
  *pInfoFlash_A = AdjBCSCTL1_1M;
  FCTL1 = FWKEY;                                     // Clear WRT bit
  FCTL3 = FWKEY + LOCKA + LOCK;       // Set LOCK & LOCKA bit // Set LOCK bit

  P1OUT |= BIT3;
  for (;;)
  {   
                                                              // 隔四秒钟输出SMCLK
  BCSCTL1 = CALBC1_1MHZ;
  DCOCTL = CALDCO_1MHZ;
  timeAdelay(2);
  P1OUT ^= BIT3;
  softwareDelay(50000);
  P1OUT ^= BIT3;
  BCSCTL1 = CALBC1_8MHZ;
  DCOCTL = CALDCO_8MHZ;
  timeAdelay(2);
  P1OUT ^= BIT3;
  softwareDelay(50000);
  P1OUT ^= BIT3;
  BCSCTL1 = CALBC1_12MHZ;
  DCOCTL = CALDCO_12MHZ;
  timeAdelay(2);
  P1OUT ^= BIT3;
  softwareDelay(50000);
  P1OUT ^= BIT3;
  BCSCTL1 = CALBC1_16MHZ;
  DCOCTL = CALDCO_16MHZ;
  timeAdelay(2);
  P1OUT ^= BIT3;
  softwareDelay(50000);
  P1OUT ^= BIT3;
  }
}

//------------------------------------------------------------------------------

void Set_DCO (unsigned int delta, char *pBcsctl1_, char *pDcoct_) // Set DCO to selected frequency
//------------------------------------------------------------------------------
{
unsigned int Compare, Oldcapture = 0;


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

  while (1)
  {

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

    if (delta == Compare) break;         // If equal, leave "while(1)"
    else if (delta < Compare)               // DCO is too fast, slow it down
  {
    DCOCTL--;
    if (DCOCTL == 0xFF)
    {
      if (!(BCSCTL1 == (XT2OFF + DIVA_3)))
      BCSCTL1--;                                             // Did DCO roll under?, Sel lower RSEL
    }
  }
  else
  {
    DCOCTL++;
    if (DCOCTL == 0x00)
    {
          if (!(BCSCTL1 == (XT2OFF + DIVA_3 + 0x0F)))
          BCSCTL1++;                                         // Did DCO roll over? Sel higher RSEL
      }
  }
  softwareDelay(20);
}

    CCTL2 = 0;                                               // Stop CCR2
    TACTL = 0;                                               // Stop Timer_A
    *pBcsctl1_ = BCSCTL1 & (~DIVA_3);
    *pDcoct_ = DCOCTL;
}

void softwareDelay(unsigned int time)
  {
  while(--time);
  }

void timeAdelay(unsigned int time)
{
  TACTL = TASSEL_1 + MC_2 + TACLR;     // SMCLK, cont-mode, clear
while(time)
{
  while(!(TACTL &TAIFG));
  TACTL &= ~TAIFG;
  time--;
  }
  TACTL = 0;
}

我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[0]
    暂无已审核评论!

网站导航 管理登陆 ┊ 免责声明 问题反馈  友链说明
本站部分内容来自网络共享资源,如有冒犯您的权利请来信告之删除或纠正!
不得对本站进行复制、盗链或镜像,转载内容须获得同意或授权;欢迎友情链接、站务合作!

    我要报警 Alexa
 mcusy_cn#126.com (请把#改成@) 交流:522422171
本站学习交流群:138..158(高级群1-)、77930286(高级群2)、61804809(群3)
Copyright© MCUSY All Rights Reserved
本站网警备案号: WZ36040002485
  ICP备案证书号:粤ICP备09034963号