Jump to content
Sign in to follow this  
AGlass0fMilk

MSP430 Frequency Counter

Recommended Posts

I am trying to make a frequency counter in order to experiment with the MSP430G2553. But as a beginner to microcontrollers (although not programming), it is proving harder than I thought (an operating system certainly hides a lot!)

 

This project is supposed to be able to measure quite low frequencies (at most ~1.5kH) and I need to sample multiple frequencies at a time.

 

From my understanding of the research I've currently done, one possible (quick) formula to measure a frequency is to start a counter at the rising edge of a frequency, and then stop it at the next rising edge of a frequency, take the value and then find the reciprocal (1/counter_value) or sample the frequency like this for multiple cycles and then find the average. I also believe that one possible way to do this is to use the Timer_A peripheral of the MSP430G2553 in capture mode, which I understand to have 3 channels for capture (which means I can determine 3 different frequencies with one chip simultaneously?).

 

But where I am having trouble is the actual programming aspect of this project as I am new to microcontrollers and I am quickly realizing that there is a lot more to programming embedded systems than desktop computers! :lol:

 

I have a couple of questions:

 

Are my described methods correct/efficient/accurate? If not, what is the best formula for determining a frequency real-time (it must be done as fast as possible)

 

Is my assumption that 3 frequencies (channels) may be analyzed by Timer_A at once correct? Or are there more/less channels available?

 

How do I set up the Timer_A to be sourced by an external 32kH watch crystal? (Apparently Internal DCOs are notoriously inaccurate)

 

I know I should look at the User Guide/Datasheet, but there's a lot of information in there and it is a skill itself to be able to navigate and pick out the information you need quickly, so can you point me towards certain sections/examples to help me set this up?

Share this post


Link to post
Share on other sites

Timer A setup --this is for the 2452/53 the bare minimum settings --no ISR

 

 

TACTL |= TASSEL_1; //sets Timer A to ACLK

 

TACCTL0 |= MC_1 + CAP; //sets up Capture/compare register for Capture on rising edge and enable capture

 

TACCTL1 |= MC_1 + CAP;

 

TACCTL2 |= MC_1 + CAP;

 

in TACCTLx register there is a setting to tell it what pin or internal connection to activate the Capture function.

CCISx 00 CCCIxA

01 CCIxB

10 grnd

11 vcc

 

This setting allows you to use either an external pin or SW to use the capture function , I would definitely read CH12 in SLA144x.pdf Family user guide, x= version letter

 

Your approach to the whole thing should work correctly, and you may be able to find some examples from iDave, he has been working on the "TAOS light to frequency IC" but dont know if he has posted any code

Share this post


Link to post
Share on other sites

It appears that the MSP430G2553 actually has two 16-bit Timers (Timer0_A and Timer1_A)! Which I believe means I have 6 Capture/Compare channels, which is a good number for my project. The only problem is that the TACCRO1 and TACCRO2 are grouped into the TAIV interrupt vector but it probably won't be that big of a problem.

 

EDIT:

It also appears that there is no external input pin for TA0CCTL2 so I may only be able to have 5 inputs :(

Share this post


Link to post
Share on other sites

I have been reading the datasheet and family user guide and have found out more about the MSP430G2553's two Timer_As. For my project, I want interrupts enabled so I have written some extra code. I have also looked at demos that are designed do to things similar to what I am trying to do, but my code isn't working. There's a lot to initialize that I don't fully understand yet so bear with me. I am testing my code with a 555 timer that is set to emit around 500Hz, but nothing happens when I apply the output to P2.0 (the pin I am testing with) Here's the code:

 

#include

void main(void)
{
 volatile unsigned int i;
 WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer

 for (i=0; i<20000; i++)                   // Delay for crystal stabilization
 {
 }

 //TA0CTL |= TASSEL_1 + TAIE; //sets Timer A to ACLK - 32768Hz Watch Crystal with Interrupts
 TA1CTL |= TASSEL_1 + TAIE;
 P1DIR |= BIT0 + BIT6; //P1.0 and P1.6 Outputs (Red/Green LEDs)
 P1OUT &= ~BIT0; //Red LED off
 P1OUT |= BIT6; //Green LED on
 P2DIR &= ~BIT0; //P2.0 Input
 //Set P2.0 to Primary Peripheral function
 P2SEL |= BIT0;

 //Sets up Capture/Compare register for Capture on rising edge and enable capture
 TA1CCTL0 |= CM_1 + SCS + CCIS_0 + CAP + CCIE; //Timer1_A : CCI0A - Capture on P2.0
 //CC Register: TA1CCR0

 _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt
}

//Timer_A1 TACCR0 Interrupt Vector Handler Routine
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer1A0(void)
{
P1OUT |= BIT0; //Turn on Red LED
}

But when I apply the output of the 555 timer circuit onto P2.0, the Red LED does not turn on, so what could be going wrong? What is there still to set? Sorry that the code is kinda messy.

Share this post


Link to post
Share on other sites

One error is in line:

TA1CTL |= TASSEL_1 + TAIE;

Your timer not running. Edited line:

TA1CTL |= TASSEL_1 + TAIE + MC_2;
/* Timer A mode control: 2 - Continous up */

And into interrupt routine maybe try this (you can see all captures, not only the first ...):

P1OUT ^= BIT0; // Toggle Red LED using exclusive-OR

Share this post


Link to post
Share on other sites

I have been experimenting with MSP430G2553 for a while now, I have the hardware UART sending the measured frequencies to my computer through the USB and I have successfully measured PWM'd signals accurately. I have been reading the user guides for both the family and the specific chip I have, and I came across the fact that you can set P1 and P2 interrupts to go off on rising edges, much like the Capture/Compare function of Timer_A. But since I need more than 5 capture ports (which is how many my device supports externally) I was thinking:

 

What is the difference between having the Capture/Compare module interrupt on the rising edge and take the value of Timer_A's counter and having P1 or P2 interrupt on the rising edge and take the value of Timer_A's counter? Other than the fact that the C/C module is specifically designed for that purpose, would it be the same?

 

This would allow me to use 1 Microcontroller in the circuit instead of 2, which is much more elegant and desirable.

Share this post


Link to post
Share on other sites

It takes some time to respond to an interrupt, so the value you read from the timer will always be a bit off. There are many things that affect interrupt latency, so it is not possible to compensate for it accurately.

 

The timer capture will save the timer value when a pin changes state and then optionally trigger an interrupt. The interrupt latency does not matter because the timer value has been saved in the capture register.

Share this post


Link to post
Share on other sites

Depending on your clock speed and the response time required it might not matter at all. If, for example, you are keeping track of time in seconds and want to know on which second the input changed, then it certainly doesn't matter if you use TimerA capture or Pin change interrupts.

 

However, for most applications you want to get as accurate a reading as possible, for which the capture registers are ideal. To give you an example, the interrupt latency in a recent PIC project I was working on was 11 clock cycles (depending on certain parameters this could go up significantly). Accounting for interrupt latency is important if you are interested in accuracy at 1/Fosc kind of scale. (If you use a 1MHz clock for example, you might wanna watch out for latency if you care about microsecond accuracy)

 

So basically you want to watch out for interrupt latency, but keep in mind that it won't unbearably long!

 

Hope this helps!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×