EmbeddedRelated.com
Forums

MSP430 DCO operation

Started by mjruley August 28, 2002
I am interested in using the DCO for MCLK and SMCLK with a 32 KHz 
crystal generating an interrupt on TIMERB . How much software 
overhead is needed to maintain lock for the DCO with the 32 KHz 
interrupt? Ideally, the DCO will be off most of the time so how time 
consuming is the re-synchronization effort? We are planning on using 
the DCO clock to do precise timing measurements using TIMERA so 
effective DCO operation is important.

I'd like to hear of your experiences in this area.


Beginning Microcontrollers with the MSP430

Here's my experience with the DCO. It's not wuite the same as what you're doing, but it may help.
 
I began by reading TI's app note SLAA116, which is available on their web site. It is an app note on building a PWM, but it contains a cal routine for the DCO. I then adapted this for my use.
 
I am busy in the development stage with this, so I can't answer a lot of questions, at least right now. However, I have had *good* results (apparently, so far) with my app using the DCO; I need relatively little accuracy, I am maintaining a second counter for the user's display, and 1/8 and 1/512 second interrupts within. I am timing the duration of a charge or discharge cycle of a pack of NimH cells.
 
I calibrate the DCO every 1/8 second.
 
 
****Here is where I initialize TIMER_B (partial):
 
   // TB6 capture mode selected,
   // connect TB6 capture module to ACLK,
   // capture on rising edge.
   // Object is to capture # of timer B counts in 1/8 second.
   // Then, DCO can be calibrated
   TBCCTL6 |= CAP | CCIS_1 | CM_1;
 
****Here is my TIMER_B interrupt service function:
 
You can see I'm using the timer for multiple stuff, but the applicable code
is in case 0x0a: No attempt has been made to optimize this, because my
application works fine with what you see here.
/****************************************************
* Handles TIMER_B interrupts for module 1 through 6 *
****************************************************/
interrupt[TIMERB1_VECTOR] void IntTimerB(void)
{
   switch (TBIV) {
      case 0x02:
         break;
      case 0x04:
         // load next compare value.
         // Handles 10KHz squarewave output
         TBCCR2 += RLD_TMRB_2;
         TBCCR2 &= 0xfff;
         break;
      case 0x06:
         break;
      case 0x08:
         break;
      case 0x0a:
         break;
         // here for DCO cal interrupt
      case 0x0c:
         CalDco();
         break;
      case 0x0e:
         break;
      default:
         break;
   }
}
 
****Here is my CalDco function, which is called periodically fromthe TIMER_B interrupt:
This is called 8 times/second. Again, no attempt to optimize.
/***************************************************************
* Periodically recalibrates DCO for maximum accuracy over time *
* Uses TB6 module capture register                             *
* TB6 capture triggered by ACLK rising edge, so TB6 captures   *
* the number of SMCLK's in a ACLK                              *
***************************************************************/
void CalDco(void)
{
   static unsigned int   LastCap;   // holds last capture value
   // guaranteed initialization = 0 K&R p. 85
   unsigned int    delta;      // holds calc'ed dif between last cap and current cap values     
  
   // get TBCCR6 value immediately before it changes.
   delta = TBCCR6;
   // first time, so just save capture value for next time
   if (LastCap == 0)
      LastCap = delta;
   // not first time, so we have something to compare.
   else {
      TBCCTL6 &= ~CCIE;   // disable capture interrupt
      // at each interrupt, DCOCTL will be adjusted 1 count.
      delta -= LastCap;
      delta &= 0xfff;
      if ((delta < TARGET_DCO_COUNT) && (DCOCTL < DCOCTL_MAX))
         DCOCTL++;
      else if ((delta > TARGET_DCO_COUNT) && (DCOCTL > DCOCTL_MIN))
         DCOCTL--;
      LastCap = 0;   // set up for next correction
   }
}
 
 
----- Original Message -----
From: "mjruley" <mjruley@yahoo.com>
To: <msp430@yahoogroups.com>
Sent: Wednesday, August 28, 2002 8:01 AM
Subject: [msp430] MSP430 DCO operation

> I am interested in using the DCO for MCLK and SMCLK with a 32 KHz
> crystal generating an interrupt on TIMERB . How much software
> overhead is needed to maintain lock for the DCO with the 32 KHz
> interrupt? Ideally, the DCO will be off most of the time so how time
> consuming is the re-synchronization effort? We are planning on using
> the DCO clock to do precise timing measurements using TIMERA so
> effective DCO operation is important.
>
> I'd like to hear of your experiences in this area.
>
>
> ------------------------ Yahoo! Groups Sponsor ---------------------~-->
> 4 DVDs Free +s&p Join Now
>
http://us.click.yahoo.com/pt6YBB/NXiEAA/MVfIAA/CFFolB/TM
> ---------------------------------~->
>
> ">msp430-unsubscribe@egroups.com
>
>  
>
> ">http://docs.yahoo.com/info/terms/
>
>


I really don't think you need to calibrate the DCO every 1/8th second!  It will drift due to ambient temp changes but unless your environment's going all over the place, it should be pretty stable once you calibrate.  Every minute or so even seems conservative.
 
Bruce
-----Original Message-----
From: Mark Skeels [mailto:meskeels@earthlink.net]
Sent: Wednesday, August 28, 2002 7:37 AM
To: msp430@yahoogroups.com
Subject: Re: [msp430] MSP430 DCO operation

Here's my experience with the DCO. It's not wuite the same as what you're doing, but it may help.
 
I began by reading TI's app note SLAA116, which is available on their web site. It is an app note on building a PWM, but it contains a cal routine for the DCO. I then adapted this for my use.
 
I am busy in the development stage with this, so I can't answer a lot of questions, at least right now. However, I have had *good* results (apparently, so far) with my app using the DCO; I need relatively little accuracy, I am maintaining a second counter for the user's display, and 1/8 and 1/512 second interrupts within. I am timing the duration of a charge or discharge cycle of a pack of NimH cells.
 
I calibrate the DCO every 1/8 second.
 
 
****Here is where I initialize TIMER_B (partial):
 
   // TB6 capture mode selected,
   // connect TB6 capture module to ACLK,
   // capture on rising edge.
   // Object is to capture # of timer B counts in 1/8 second.
   // Then, DCO can be calibrated
   TBCCTL6 |= CAP | CCIS_1 | CM_1;
 
****Here is my TIMER_B interrupt service function:
 
You can see I'm using the timer for multiple stuff, but the applicable code
is in case 0x0a: No attempt has been made to optimize this, because my
application works fine with what you see here.
/****************************************************
* Handles TIMER_B interrupts for module 1 through 6 *
****************************************************/
interrupt[TIMERB1_VECTOR] void IntTimerB(void)
{
   switch (TBIV) {
      case 0x02:
         break;
      case 0x04:
         // load next compare value.
         // Handles 10KHz squarewave output
         TBCCR2 += RLD_TMRB_2;
         TBCCR2 &= 0xfff;
         break;
      case 0x06:
         break;
      case 0x08:
         break;
      case 0x0a:
         break;
         // here for DCO cal interrupt
      case 0x0c:
         CalDco();
         break;
      case 0x0e:
         break;
      default:
         break;
   }
}
 
****Here is my CalDco function, which is called periodically fromthe TIMER_B interrupt:
This is called 8 times/second. Again, no attempt to optimize.
/***************************************************************
* Periodically recalibrates DCO for maximum accuracy over time *
* Uses TB6 module capture register                             *
* TB6 capture triggered by ACLK rising edge, so TB6 captures   *
* the number of SMCLK's in a ACLK                              *
***************************************************************/
void CalDco(void)
{
   static unsigned int   LastCap;   // holds last capture value
   // guaranteed initialization = 0 K&R p. 85
   unsigned int    delta;      // holds calc'ed dif between last cap and current cap values     
  
   // get TBCCR6 value immediately before it changes.
   delta = TBCCR6;
   // first time, so just save capture value for next time
   if (LastCap == 0)
      LastCap = delta;
   // not first time, so we have something to compare.
   else {
      TBCCTL6 &= ~CCIE;   // disable capture interrupt
      // at each interrupt, DCOCTL will be adjusted 1 count.
      delta -= LastCap;
      delta &= 0xfff;
      if ((delta < TARGET_DCO_COUNT) && (DCOCTL < DCOCTL_MAX))
         DCOCTL++;
      else if ((delta > TARGET_DCO_COUNT) && (DCOCTL > DCOCTL_MIN))
         DCOCTL--;
      LastCap = 0;   // set up for next correction
   }
}
 
 
----- Original Message -----
From: "mjruley" <mjruley@yahoo.com>
To: <msp430@yahoogroups.com>
Sent: Wednesday, August 28, 2002 8:01 AM
Subject: [msp430] MSP430 DCO operation

> I am interested in using the DCO for MCLK and SMCLK with a 32 KHz
> crystal generating an interrupt on TIMERB . How much software
> overhead is needed to maintain lock for the DCO with the 32 KHz
> interrupt? Ideally, the DCO will be off most of the time so how time
> consuming is the re-synchronization effort? We are planning on using
> the DCO clock to do precise timing measurements using TIMERA so
> effective DCO operation is important.
>
> I'd like to hear of your experiences in this area.
>
>
> ------------------------ Yahoo! Groups Sponsor ---------------------~-->
> 4 DVDs Free +s&p Join Now
>
http://us.click.yahoo.com/pt6YBB/NXiEAA/MVfIAA/CFFolB/TM
> ---------------------------------~->
>
> ">msp430-unsubscribe@egroups.com
>
>  
>
> ">http://docs.yahoo.com/info/terms/
>
>






">Yahoo! Terms of Service.


Thanks, Bruce.
 
I actually have no idea how often the DCO needs calibration; I had the convenience of 1/8 second interrupt, so put it in there.
 
Is there any downside to calibration this often?
 
Mark
 
----- Original Message -----
From: Bruce Cannon
To: msp430@yahoogroups.com
Sent: Thursday, August 29, 2002 12:45 PM
Subject: RE: [msp430] MSP430 DCO operation

I really don't think you need to calibrate the DCO every 1/8th second!  It will drift due to ambient temp changes but unless your environment's going all over the place, it should be pretty stable once you calibrate.  Every minute or so even seems conservative.
 
Bruce
-----Original Message-----
From: Mark Skeels [mailto:meskeels@earthlink.net]
Sent: Wednesday, August 28, 2002 7:37 AM
To: msp430@yahoogroups.com
Subject: Re: [msp430] MSP430 DCO operation

Here's my experience with the DCO. It's not wuite the same as what you're doing, but it may help.
 
I began by reading TI's app note SLAA116, which is available on their web site. It is an app note on building a PWM, but it contains a cal routine for the DCO. I then adapted this for my use.
 
I am busy in the development stage with this, so I can't answer a lot of questions, at least right now. However, I have had *good* results (apparently, so far) with my app using the DCO; I need relatively little accuracy, I am maintaining a second counter for the user's display, and 1/8 and 1/512 second interrupts within. I am timing the duration of a charge or discharge cycle of a pack of NimH cells.
 
I calibrate the DCO every 1/8 second.
 
 
****Here is where I initialize TIMER_B (partial):
 
   // TB6 capture mode selected,
   // connect TB6 capture module to ACLK,
   // capture on rising edge.
   // Object is to capture # of timer B counts in 1/8 second.
   // Then, DCO can be calibrated
   TBCCTL6 |= CAP | CCIS_1 | CM_1;
 
****Here is my TIMER_B interrupt service function:
 
You can see I'm using the timer for multiple stuff, but the applicable code
is in case 0x0a: No attempt has been made to optimize this, because my
application works fine with what you see here.
/****************************************************
* Handles TIMER_B interrupts for module 1 through 6 *
****************************************************/
interrupt[TIMERB1_VECTOR] void IntTimerB(void)
{
   switch (TBIV) {
      case 0x02:
         break;
      case 0x04:
         // load next compare value.
         // Handles 10KHz squarewave output
         TBCCR2 += RLD_TMRB_2;
         TBCCR2 &= 0xfff;
         break;
      case 0x06:
         break;
      case 0x08:
         break;
      case 0x0a:
         break;
         // here for DCO cal interrupt
      case 0x0c:
         CalDco();
         break;
      case 0x0e:
         break;
      default:
         break;
   }
}
 
****Here is my CalDco function, which is called periodically fromthe TIMER_B interrupt:
This is called 8 times/second. Again, no attempt to optimize.
/***************************************************************
* Periodically recalibrates DCO for maximum accuracy over time *
* Uses TB6 module capture register                             *
* TB6 capture triggered by ACLK rising edge, so TB6 captures   *
* the number of SMCLK's in a ACLK                              *
***************************************************************/
void CalDco(void)
{
   static unsigned int   LastCap;   // holds last capture value
   // guaranteed initialization = 0 K&R p. 85
   unsigned int    delta;      // holds calc'ed dif between last cap and current cap values     
  
   // get TBCCR6 value immediately before it changes.
   delta = TBCCR6;
   // first time, so just save capture value for next time
   if (LastCap == 0)
      LastCap = delta;
   // not first time, so we have something to compare.
   else {
      TBCCTL6 &= ~CCIE;   // disable capture interrupt
      // at each interrupt, DCOCTL will be adjusted 1 count.
      delta -= LastCap;
      delta &= 0xfff;
      if ((delta < TARGET_DCO_COUNT) && (DCOCTL < DCOCTL_MAX))
         DCOCTL++;
      else if ((delta > TARGET_DCO_COUNT) && (DCOCTL > DCOCTL_MIN))
         DCOCTL--;
      LastCap = 0;   // set up for next correction
   }
}
 
 
----- Original Message -----
From: "mjruley" <mjruley@yahoo.com>
To: <msp430@yahoogroups.com>
Sent: Wednesday, August 28, 2002 8:01 AM
Subject: [msp430] MSP430 DCO operation

> I am interested in using the DCO for MCLK and SMCLK with a 32 KHz
> crystal generating an interrupt on TIMERB . How much software
> overhead is needed to maintain lock for the DCO with the 32 KHz
> interrupt? Ideally, the DCO will be off most of the time so how time
> consuming is the re-synchronization effort? We are planning on using
> the DCO clock to do precise timing measurements using TIMERA so
> effective DCO operation is important.
>
> I'd like to hear of your experiences in this area.
>
>
> ------------------------ Yahoo! Groups Sponsor ---------------------~-->
> 4 DVDs Free +s&p Join Now
>
http://us.click.yahoo.com/pt6YBB/NXiEAA/MVfIAA/CFFolB/TM
> ---------------------------------~->
>
> ">msp430-unsubscribe@egroups.com
>
>  
>
> ">http://docs.yahoo.com/info/terms/
>
>






">Yahoo! Terms of Service.






">Yahoo! Terms of Service.


I actually have no idea how often the DCO needs calibration; I had the convenience of 1/8 second interrupt, so put it in there.
 
I understand, just thought I'd mention it.
 
 Is there any downside to calibration this often?
 
 I'd say not if you don't care about the activity.
 
 Mark 
 
Bruce