Thursday, March 15, 2012

Using ACLK and the 32kHz Crystal

The other day I decided to build a timer to control some lights in my apartment. As I hope to expand this mini project into a full-fledged home automation system built around the CC430, a simple light timer from Walmart would not do! Obviously, the LaunchPad is the perfect tool for the job.

For example, let's say that I wanted to keep my lights on for 5 hours at night while I am on vacation. The first thing you will need is a way to tell time; this requires some sort of real-time clock. Since the high frequency clock sources on the MSP430 are not accurate enough to keep reliable time over a large period of time (anything greater than 1 minute in my opinion), a lower frequency clock will be needed. Though many of the newer MSP430s have built in 32kHz clocks, such as the the MSP430F5510, the value line series does not!

The 32.768kHz Crystal

The first step for building this project is to install the 32.768kHz crystal onto the LaunchPad. From this point onward I will just be calling this 32kHz for simplicity. You might be wondering why a real time clock is based on 32.768kHz; 32768 is exactly 2^15. This number can be divided down using binary values to give you a frequency of 1Hz, or a period of 1 second. This is why 32kHz is the standard frequency used in real-time clocks.


The above image shows the crystal soldered onto my LaunchPad. There are many methods you can use to solder this on, one of which is nicely documented on Justin's Tech blog. I ended up soldering the base of the crystal first, ensuring that the clock was positioned correctly before I soldered the small leads. Use any method that works for you.

The LED Hello World

The first thing you should do once you have this soldered onto your board, is test it. Making sure that everything works before you start a complicated project is very important. Let's make an LED turn on every two seconds, for one second. Instead of changing the timer output pins directly as we did in an earlier post, lets blink the LED manually so that we can easily expand the functionality of this program in a future post. There are a few things you should notice in the code below.

In this code we divide the clock by 64 (lines 26 and 37) which causes the timer to increment 512 times a second (512Hz). Once the clock counts up to 512 511 (this is because we start counting at 0), one second has gone by, and an interrupt is thrown. Now that we are entering an interrupt routine instead of automatically toggling the output, we can use this interrupt routine in the future to expand the functionality of this code.

The last important line of code is line 27, where a capacitance value is set. This value matches the capacitors that come installed on your LaunchPad. In the next section, I will elaborate slightly on what this capacitance is.

Edit: This statement is actually incorrect. A big thank you goes out to Jens-Michael Gross for pointing it out to me.
"The capacitance setting is an internal switch that enables some silicon capacitors on the MSP die. The selection has to match the required load capacitance of the used watch crystal. You can set it to minimum (plain parasitic pin capacitance) and apply external capacitors of the proper value, if you want. However, the available options are sufficient for the most watch crystals, so external capacitors are unnecessary, even counterproductive. And external capacitors have a large tolerance that affects the crystal frequency. The LaunchPad I just got has no capacitors installed (the C21 and C22 pads are empty, as it should be if the XCAP options are used."
Custom Design

One thing I wanted to mention before this post comes to a close, is how you can take this design off the LaunchPad and make it your own. Many projects work out so well that you just want to create a PCB or make it permanent in some other way.

Working with crystals can be tricky for beginners, as there is one thing you must look out for. All crystals require a load capacitance to remain stable, Wikipedia (Pierce Oscillator) and Texas Instruments both have some quality information on the topic. The value of these two capacitors depend on which crystal you use. Even two crystals with the same frequency which are made by the same manufacture might require different load capacitor values. Please check the crystal's datasheet for this information. For example, the LaunchPad uses 12pF capacitors to load the crystal we just installed, yet many crystals require 22pF.

Edit: This statement is actually incorrect. Another big thank you goes out to Jens-Michael for pointing it out to me. Thanks for reading!
"12pF is the typical load for most crystals I've ever seen. But due to the electric connection, a 12pF load means [there will be 2] 24pF capacitance on each of the crystals sides. Reason is that (seen from the crystal), the two capacitors are in series to each other and parallel to the crystal. […] Subtract the ~2pF pin capacitance of the MSPs pins and you get [two separate] 22pF [for] external capacitors, resulting in 12pF load. The XCAP settings already include pin capacitance and the /2 factor."
A bit more information and great advice from Jens-Michael!
"Experiments have shown that the G devices (in opposition to the AFE2x and some other x2 family devices without HFXT1 input) will accept a high-frequency TTL clock signal (e.g. from a self-oscillating quartz oscillator) on the XTIN pin, when in bypass mode. The Datasheet limits external clock to 50kHz, but there were no problems with 16MHz."
Conclusion

As you can see by the following screenshot from my oscilloscope, this timer is pretty darn accurate.


Hopefully you enjoyed this post and found it informative. I am going to try to keep things a bit more bite-sized from now on. Let me know what you think.

Post links to your projects which use the ACLK or the 32kHz crystal in the comment section below!

38 comments:

  1. "When using a timer on the MSP430, it is important to divide the source clock down to a reasonable frequency", why? is it more engery efficient or is there some other reason

    ReplyDelete
    Replies
    1. Nice catch! I should have been a bit more clear with that statement.

      Edit: "When using a timer on the MSP430 to keep track of long periods of time, it is important to divide the source clock down to a reasonable frequency."

      Why? Let me give you an example: if you are using a 16MHz clock to measure out 1 second, you need 16 million timer cycles to get this value. Since the timer is a 16-bit timer, you can only count up to 2^16. By diving the 16MHz clock by 512 (8*8*8), you get a base frequency of 31.25kHz. Now you can use your 16-bit timer to count up to a second by setting the compare register to 31250.

      Delete
    2. hm ok but for 32768 Hz you wouldnt have to divide the clock since that is (as you stated) 2^15 and therefore within the range of the timer register

      Delete
    3. Correct. Originally I was going to have the timer keep track of every minute, not every second. If this were the case, the clock would have to be divided down. I will remove that statement from the post, hopefully it will alleviate some confusion.

      Thanks!

      Delete
  2. Thanks for nice project. question: Can I use MSP430G2231, if so should "TIMER0_A0_VECTOR" be changed to "TIMERA0_VECTOR"
    Are there other changed I must do?

    ReplyDelete
    Replies
    1. I believe that is the only thing that needs to be changed. If you create a project in CCS and attempt to run the code, it will tell you if you have any errors. You can check in the devices header file if you cannot determine what the correct definition is.

      Delete
  3. Are you going to transfer this code over to a CC430 in the future? Or are you planning on sticking to a Launchpad and using and external radio (i.e. a CC2000 series device)?

    ReplyDelete
    Replies
    1. Good question. The current plan is to transfer the code to a CC430. I am in the process of building a small CC430 module, hopefully the first prototype will work well enough to continue forward. Once I have more free time, I will be able to finish the layout.

      Delete
    2. Nice! I would love to see how you go through all the board design and changing of code to make it work on a CC430. I am in the planning stages of either using a CC430 or a MSP430 + C2000 radio to a low-power application as well... I would like to see how your project develops over time!

      Keep up the good work

      Delete
  4. Hi,
    I have a 32K crystal, and I want timer to trigger after 1 minute. Is it possible to do so ?
    At this point my timer setting is:
    TACTL = TASSEL_1 | MC_2 | ID_3 | TAIE; //gives me 32k/ (8*64 K) = trigger after 16 second.
    Then I used a global variable , volatile minute_counter.
    #pragma vector=TIMERA1_VECTOR
    __interrupt void Timer_A (void)
    {
    switch (TAIV)
    {
    case 2: //CCR1
    break;
    case 4: //CCR2
    break;

    case 10: //once every 1 minute
    minute_one++;
    if (minute_one ==4)
    {
    my_code_to_do_stuff_after_this_trigger;
    }
    break;
    }
    _BIC_SR_IRQ(LPM3_bits); // Exit LPM3 after reti
    }

    Will this work?
    At this moment it is stuck in some UART code, and I cant debug it.
    Thanks

    ReplyDelete
  5. Do you know what Makey Makey is? If not google for it. It is based on Arduino, it would be great to make it on a MSP430 Launchpad base!
    bye

    ReplyDelete
  6. Hi,
    I am really confused about the accuracy of clock in MSP430 lauhchpad devices. I am using msp430g2231 and 2553. In your example, it is working in Lowpower mode 3. I tried the above code without usign the LPM3, and instead I am doing some other operations in a while loop. Then it is not triggring the interrupt. So the timer will use the ACLK only when it is in LPM3?

    I used PIC,AVR etc and there I can use the external Hf crystal and I can achieve a great accuracy but here in MSP430 launchpad, still I don't know how to do things with such accuracy.

    ReplyDelete
  7. Okay am sorry, I forgot to activate the GIE. Now its working not only in lpm, but the other mode also..

    ReplyDelete
  8. hey GREAT WORK..........explains everything in a well defined manner
    but can u pls group all the tuts on msp430 in an ascending order as it is very difficult to find the tuts
    thx reply soon.............

    ReplyDelete
  9. can we use a crystal of higher frequency than the normal 32KHz available with the launchpad?

    ReplyDelete
    Replies
    1. According to the datasheet on the MSP430G2553, the crystals which you can use on XT1 must be between 10kHz and 50kHz. I'm there these numbers can be stretched a bit (although it is not recommended). You should ask on the e2e.ti.com forums fora more detailed explanation.

      Delete
  10. My clock is acting strangely because it seems that my XIN has no pull-up or pull-down. The interrupts are delayed and erratic.

    However, when I pull XIN up or down manually using an external resistor, the timer works perfectly.

    I'm using your code exactly as posted here.

    Any idea how I can enable the internal pullup or pulldown resistors for XIN? Is there something similar to writing 1 or 0 (for pullup/pulldown) to the respective bit in PxOUT and then writing 1 to the respective bit PxREN?

    ReplyDelete
    Replies
    1. As long as you are using the crystal provided in the LaunchPad kit and follow the directions exactly (and keep the code the same), everything should work fine. There is no reason to hook up a pull-up or pull-down resistor to a crystal, it is just not how they work. It might be possible that you have a solder bridge somewhere as well. Sorry I can't be of more help.

      Delete
  11. I am completely new to msp430. I want to use this board for controlling some LEDs accurately in the order of milliseconds. By the explanation that has been given it seems that the minimum is 1 second. Is that so?

    ReplyDelete
    Replies
    1. Actually, by changing a few parameters you can change the interrupt time to anything you want (as long as it is less than your clock rate). Check out one of my earlier posts for more information on MSP430 timers.

      http://www.msp430launchpad.com/2010/07/timers-and-clocks-and-pwm-oh-my.html

      Delete
  12. Hi Nicholas, has the "printf()" been revised to be used in a MSP430G2553.
    I am unable to use it in the form as available on your blog
    of 08 June 2012.

    ReplyDelete
  13. I tested your code but led was turn on cca 2,5s. When I changed CCR0 on 30720 led turn on cca 2:30 (2.5m). Can you help my?

    ReplyDelete
    Replies
    1. HI,
      I am having the same problem, with CCR0 = 511; the cycle time is about 2.5s.
      Is there something wrong with the way I inserted the Xtal?

      Did you work out what your problem was?

      Delete
    2. I recommend pulling ACLK out to an external pin so that you can measure it with a scope or logic analyzer. If your clock speed is wrong, check the registers to make sure it is setup correctly for your device, and check the solder job. Best of luck!

      Delete
  14. This code does not work as intended: The clock is off by about 0.2%. The family guide has the following description for MC_1: "The timer repeatedly counts from zero to the value of TACCR0". So if you count from 0 to 512, the frequency is actually 512/513 Hz.

    ReplyDelete
    Replies
    1. Thank you for pointing that out. This is a perfect example of a mistake that is very easy to make that has very real consequences for certain applications. A 0.2% error in the timer results in an error of over 2.5 minutes a day. Thank you again.

      Delete
  15. This comment has been removed by the author.

    ReplyDelete
  16. Nice post. I was having trouble with finding a good reference to setting up the ACLK for the last few days, but this seems to answer most of my questions.

    One thing I am not sure on, does setting ID_3 work for the ACLK? The family users guide was unclear on this part, it seemed like it only was used on the DCO when it was used for the timer.

    Another thing, shouldn't the caps be set to 12.5 pF by default? At least this should seem the case, if not I am very surprised I got my circuit to work when I hooked it up to a breadboard without adding load capacitors.

    I also want to thank Jens-Michael, I have been seeing his work on the forums for the MSP430 page and they have been super helpful.

    ReplyDelete
  17. can you tell me how you get 512 hz from 32768 hz, as i am not getting the calculation

    ReplyDelete
    Replies
    1. As posted on 9/1/13 and 9/2/13, this gives an error of 0.2%

      Delete
    2. For a 32768 Hz crystal, you have clock ticks that are spaced out with a period of 1/32768. If you want 512 Hz, you want a period of 1/512. You need (1/512)/(1/32768) clock ticks at 32768 Hz to get clock of 512.

      Another simpler way to think about it is how many times does 512 go into 32768? You need 32768/512 = 64 clock ticks to have a 512 Hz clock.

      As Barrett noted, you have to be careful with how you count clock ticks. 0 to 512 is 513 ticks, which results in an error of 0.2%.

      Delete
  18. i want service routine to be triggered at every 100ms.

    Is this possible with the 32KHz clock ?

    ReplyDelete
    Replies
    1. It is impossible to get exactly a clock that triggers exactly every 100ms using a 32kHz crystal. The closest you can get is with a clock divider of 3277. This results in 3277/32768 = 100.006 ms.

      Delete
    2. which is better method,
      1. accessing counter register for millisecond reading and implementing 1 second interrupt
      2. implementing 100 ms interrupt.

      Thanks NJC

      Delete
    3. It depends. If you care about power consumption, your goal should be to keep the MCU asleep as much as possible. This means minimizing how long your code (including interrupts) is actively running. If you only need 1 second interrupts, set it for one second. If you need 100 ms interrupts, set for 100 ms. Not sure if I perfectly understood your question, but hopefully I answered it.

      Delete
    4. Hello NJC,

      I am still new in using RTC to generate timer actions. I have confusion as regards to your answer on setting the interrupt at every 100ms(using 32KHz crystal). How can I compare or retrieve the time in milliseconds with the previous time. For instance with the example code below:

      int t = 200;//in milliseconds
      int GetTimeMs = now; /*now is the milliseconds time to be retrieved from ACLK clock source*/
      while (now - GetTimeMs < t)
      {
      //perform an action
      }

      Delete
    5. Kingsley,

      I would highly recommend Energia to you. They abstract away the complexity of working directly with the MSP430 peripherals. The following link provides the exact functionality you need. If you are unable to use Energia for any reason, you can always look at their source code as a reference.

      http://energia.nu/reference/millis/

      Best of luck!

      NJC

      Delete

Note: Only a member of this blog may post a comment.