打印

有关MSP430F2132之DCO校正参数丢失的麻烦

[复制链接]
2096|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
今日由于工作需要,经常背着笔记本,拿着仿真器以及BSL编程器来回奔波。
巧的是赶上了一款MSP430F2132 当采用BSL编程的时候,发现内部DCO校正参数
丢失,很麻烦。于是上网发现了以为朋友写的一个程序,借鉴过来添加到工程
里面,完全解决了DCO丢失的问题。特此感谢这位朋友!
另外也为了减少重量自己做了一个转接板,把JTAG+BSL统一到一个小板子上,
携带也方便多了,以后只需要带一个仿真器就可以了!
下面先给大家一个DCO的校正程序,然后是我自己画的小板子!
#i nclude <msp430x21x2.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 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;
}
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 SetDcoConn(void)
{
     WDTCTL = WDTPW + WDTHOLD; // Stop WDT
     _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
}






相关帖子

沙发
ymind| | 2013-3-14 07:58 | 只看该作者
好方法。只是怕没有人家工厂Calibration出来的准(我估计用外部精准参考时钟来校),即以后比如跑16MHz时,靠CPU cycles来精确实现微秒延时有误差了。
我曾经也不小心擦掉了information memory,后来用同批次的msp430的信息复制过来的,也许更准点吧。

使用特权

评论回复
板凳
雁舞白沙|  楼主 | 2013-3-14 09:14 | 只看该作者
以上方法,还可以吧,能保证在2%的精度!

另外还有一个问题,如果用到信息区,结果就麻烦了。因为每次都调用的参数会发生以外的改变,怎么办?

看白沙的妙招:

首先打开,msp430x21x2.h

把里面有关DCO校正参数的地方全部删除

然后在SetDco函数里面添加

char CALBC1_16MHZ;
char CALDCO_16MHZ;

以上两个变量

最后:

   CALDCO_16MHZ = AdjpDCOCTL_16M;
     CALBC1_16MHZ = AdjBCSCTL1_16M;


     
     DCOCTL = 0;
     BCSCTL1 = CALBC1_16MHZ;                    
     DCOCTL = CALDCO_16MHZ;
     BCSCTL2|=DIVM_3;

哈哈这样的结果是,保证了信息区的客户数据,同时还调整了时钟!

使用特权

评论回复
地板
雁舞白沙|  楼主 | 2013-3-14 22:12 | 只看该作者
其实还可以不用以上两个变量,直接赋值给DCOCTL和BCSCTL1就可以了!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:学者会友QQ群:72137827 三人行,必有我师!

213

主题

789

帖子

243

粉丝