Jump to content
43oh

MSP430F550x based frequency meter


Recommended Posts

I made simple frequency meter with basic MSP430F550x board without any other parts. Only 24MHz XT2 is used. XT1 is not used, but it can stay on board, no problem. Firmware size is 1.5 kB, and it is starting from $E000, so it will work with any MSP430F550x familly member. Measuring pin is TA1CLK, sequence takes 1 second, and resolution is 1 Hz.

 

Don't have some precize clock source for calibration, so I used for checking PCM2707 3.3V USB to I2S audio bridge that I have on hand. By default word select frequency is 48 kHz, and clock is 64 * 48 kHz =  3.072 MHz.

 

For calibration use presize MHz clock. First byte in firmware file (default $7D), at location $E000 is used for calibration. If mesuring result is lower than real value, increase calibration byte value, and opposite. The Best way is to change calibration byte value by one (not +/- 10) with each step.

 

When board is pluged to USB port it will be enumerated as CDC (virtual serial port), and measured results will be displayed by any terminal tool (Hyper Terminal for Win32).

 

Measuring results with measuring pin connected to ground:

[3] 0 Hz        
[4] 0 Hz        
[5] 0 Hz        

Measuring results with measuring pin connected to 48 kHz:

[33] 48000 Hz             
[34] 48000 Hz             
[35] 47999 Hz             
[36] 48000 Hz            
[37] 48000 Hz             

Measuring results with measuring pin connected to 3.072 MHz:

[53] 3071997 Hz               
[54] 3071998 Hz               
[55] 3071998 Hz               
[56] 3071997 Hz               
[57] 3071995 Hz               
[58] 3071995 Hz               
[59] 3071995 Hz               
[60] 3071995 Hz               
[61] 3071995 Hz               
[62] 3071995 Hz               
[63] 3071995 Hz               
[64] 3071995 Hz               
[65] 3071997 Hz               
[66] 3071996 Hz                   

Firmware: fm.zip

Link to post
Share on other sites

This is great. Thanks. Can you make the source available?

 

Timer TA0 is used for counting SMCLK (24 MHz) and TA1 for input signal, both with owerflow to registers. TA0 is aranged as 400 * 60000 = 24000000. When TA0 is finished (1 second), result is in stored in R11 TA1 without need for any number calculation/conversion.

 

Part of source:

TimerA0
		inc.w R10
		reti

TimerA1
		inc.w R11
		reti

Main
		; Timer TA1 is set by default

		bis.b #BIT6, &P1SEL
            	mov.w #CCIE, &TA1CCTL0					; interrupt enabled
				
		; Timer TA0 SMCLK/1

            	mov.w #TASSEL_2, &TA0CTL				; clock source SMCLK
            	mov.w #CCIE, &TA0CCTL0					; interrupt enabled

            	mov.w #060000, &TA0CCR0

Measure
            	mov.w #0, R10
            	mov.w #0, R11
            	
            	clr.w &TA0R				; clear timer counter
            	clr.w &TA1R				; clear timer counter

		bis.w #MC0, &TA0CTL			; start timer
            	bis.w #MC1, &TA1CTL			; start timer

Wait 
		cmp.w #000400, R10 
		jne Wait

		bic.w #MC0, &TA0CTL	; stop timer
		bic.w #MC1, &TA1CTL	; stop timer		
		
		; R10 TA0 = 400 * 60000 = 24000000
		; R11 TA1 = Result

 

For Win32, CDC driver description is from TI USB Dev Pack: 1CDC_descTool.zip

Link to post
Share on other sites

cool project, I've wanted to do something like this for awhile.. will this work with only square wave signals? Some signals I deal with are 15v ptp, what would be the best way of reducing these to the logic level voltages the MSP430 expects? 

 

AFAIK it will work also with non square signals. MSP430F5xx don't have 5V tolerance I/O pins, so signal must be between 0V and 3.3V. For adjusting input signals to MSP430 check http://www.ti.com/lit/an/slaa148/slaa148.pdf

Link to post
Share on other sites

For those of you who rather play with C than assembler, a translation as true to the ASM as possible:

__interrupt TimerA0_ISR(void) // Note that the implementation of an ISR is compiler dependent
{
  ++R10;
}

__interrupt TimerA1_ISR(void) // Note that the implementation of an ISR is compiler dependent
{
  ++R11;
}

void main(void)
{
  // Timer TA1 is set by default
  P1SEL |= BIT6;
  TA1CCTL0 = CCIE; // interrupt enabled

  // Timer TA0 SMCLK/1
  TA0CTL = TASSEL_2; // clock source SMCLK
  TA0CCTL0 = CCIE; // interrupt enabled
  TA0CCR0 = 60000;

  //Measure
  R10 = 0;
  R11 = 0;
  TA0R = 0; // clear timer counter
  TA1R = 0; // clear timer counter
  TA0CTL |= MC0; // start timer
  TA1CTL |= MC1; // start timer
  while(R10 != 400); // Wait
  TA0CTL &= ~MC0; // stop timer
  TA1CTL &= ~MC1; // stop timer
  // R10 TA0 = 400 * 60000 = 24000000
  // R11 TA1 = Result
}
Link to post
Share on other sites

For those of you who rather play with C than assembler, a translation as true to the ASM as possible:

...
  TA0CCR0 = 0x6000; // the hex version of the oct constant 060000
...
  while(R10 != 256); // Wait
...
  // R10 TA0 = 400 * 60000 = 24000000
  // R11 TA1 = Result
}

OK. Both numbers 400 and 6000 are decimal values, not hex.

Link to post
Share on other sites

Updated firmware is here: fm.zip

 

Measuring cycle is 2 seconds, resolution 0.5 Hz. Calibration resolution is inceased, and changing byte value at $E000 by +/- 1, measured result will change by +/- 15 Hz @ 1 MHz. Both inputs are used (TA0CLK and TA1CLK), and both results are displayed. If on board LED is connected to P1.0 (TA0CLK) it will not disturb measurement.

 

[1] 48000.0 Hz 3072015.0 Hz
[2] 48000.0 Hz 3072014.5 Hz
[3] 48000.5 Hz 3072015.0 Hz
[4] 48000.0 Hz 3072015.0 Hz
[5] 48000.0 Hz 3072014.5 Hz
[6] 48000.5 Hz 3072014.5 Hz
[7] 48000.0 Hz 3072014.5 Hz
[8] 48000.5 Hz 3072015.0 Hz
[9] 48000.0 Hz 3072014.5 Hz
Link to post
Share on other sites
  • 3 months later...

In MSP430F550x datasheet, maximum external TACLK frequency is 25 MHz, but it seems that Timer A/B is able to capture faster signal.

 

Measuring 48 MHz with my MSP430F550x based frequency meter (with 24 MHz MCLK)...

[771] 0.0 Hz 47999113.5 Hz
[772] 0.0 Hz 47999114.5 Hz
[773] 0.0 Hz 47999115.0 Hz
[774] 0.0 Hz 47999113.0 Hz
[775] 0.0 Hz 47999113.5 Hz
Link to post
Share on other sites
  • 2 years later...

I was playing around with the timers in the MSP430G2553 as making a frequency counter test, I don't have a function generator at home so was trying to generate a PWM and then also capture and count it...still working on this and not sure it's possible!

 

However I found this post useful and modified the code a little bit to run on the MSP430G2553, I have only tested it on a 1kHz test signal from my oscilloscope but seems to work and read 1009Hz consistently.  Posted the code below so someone else might find it useful.

#include <msp430g2553.h>

/*** Global variables ***/
volatile unsigned int CounterValue = 0;
volatile unsigned int StoredCount = 0;
unsigned int Result = 0;

int main(void) {

	/*** Watchdog timer and clock Set-Up ***/
	WDTCTL = WDTPW + WDTHOLD;		// Stop watchdog timer
	BCSCTL1 = CALBC1_8MHZ;  		// Set range
	DCOCTL = CALDCO_8MHZ;   		// Set DCO step + modulation
	
	/*** GPIO Set-Up ***/
	P2DIR &= ~BIT0;				// P2.0 set as input
	P2SEL |= BIT0;				// P2.0 set to primary peripheral Timer1_A

	/*** Timer_A Set-Up ***/
	TA0CCR0 = 20000;			// 20000*400 = 8000000 or 8MHz
	TA0CCTL0 |= CCIE;			// Interrupt enable
	TA0CTL |= TASSEL_2;			// SMCLK

	TA1CCTL0 |= CCIE + CCIS_0 + CM_2 + CAP;	// Interrupt enable, capture select CCIxA, Positive edge, capture mode
	TA1CTL |= TASSEL_2;						// SMCLK

	_BIS_SR(GIE);				// Enter LPM0 with interrupts enabled

	while(1)
	{

	TA0CTL |= MC0;				// Start timer
	TA1CTL |= MC1;				// Start timer
	while(CounterValue != 400);	// Wait while CounterValue is not equal to 400
	TA0CTL &= ~MC0;				// Stop timer
	TA1CTL &= ~MC1;				// Stop timer
	Result = StoredCount;		// Store frequency in Result
	CounterValue = 0;			// Zero CounterValue
	StoredCount = 0;			// Zero StoredCount
	TA0R = 0;					// Zero Timer_A0 register
	TA1R = 0;					// Zero Timer_A1 register
	}
}

//Timer_A0 TACCR0 Interrupt Vector Handler Routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer0_A0(void)
{
	CounterValue++;
}

//Timer_A1 TACCR0 Interrupt Vector Handler Routine
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer1_A0(void)
{
	StoredCount++;
}
Link to post
Share on other sites
  • 6 months later...

I was looking at doing some further testing on this. Out of curiosity what board did you use which had the MSP430F550x? I also wonder if we used a 2nd MSP430F550x to generate the input frequency we could test higher than 48MHz?

 

I ordered some samples of the MSP430F5172IDAR but I couldn't find any low cost eval boards, only this, http://www.ti.com/tool/msp-fet430u40

Link to post
Share on other sites

I was looking at doing some further testing on this. Out of curiosity what board did you use which had the MSP430F550x? I also wonder if we used a 2nd MSP430F550x to generate the input frequency we could test higher than 48MHz?

 

I ordered some samples of the MSP430F5172IDAR but I couldn't find any low cost eval boards, only this, http://www.ti.com/tool/msp-fet430u40

 

I am using my p2p MSP430F5510 boards. One MSP430F5510 board with 48 MHz XT2 (MCLK on output pin) was used as freq generator. It can't go much higher than 48 MHz regarding freq generation.

 

@@spirilis made MSP430F5172 dev board http://forum.43oh.com/topic/2828-msp430f5172-launchpad-xl/

Link to post
Share on other sites

Looks like I'll have to design my own board or order @@spirilis PCBs because I didn't see stock on his board. I also found another open source design, http://www.rev0proto.com/wiki/index.php/MSP430F5510 that I might take a look at.

 

I'm curious about your comment on it not going higher than 48MHz. I thought the whole purpose of Timer D was to go up to 256MHz on the output.

Link to post
Share on other sites

Looks like I'll have to design my own board or order @@spirilis PCBs because I didn't see stock on his board. I also found another open source design, http://www.rev0proto.com/wiki/index.php/MSP430F5510 that I might take a look at.

 

I'm curious about your comment on it not going higher than 48MHz. I thought the whole purpose of Timer D was to go up to 256MHz on the output.

Timer_D is special and can generate a 256MHz PWM signal from a 16MHz base CPU clock.  It has an FLL or PLL I believe.  Main CPU isn't rated above 25MHz (although I managed to get it to run at 56MHz briefly doing an LED blink).

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...