This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

PWM and Timer Capture on MSP430G2553

Other Parts Discussed in Thread: MSP430G2553

Hi all,

Have to admit it's been a awhile since I used the MSP430G series, but revisiting the controller for a basic project.  The aim is to create a simple frequency counter and due to the lack of a function generator at home, I thought I would use the MSP430 to generate a PWM and then count the rising or falling edges of this generated pulse train.

I know a frequency counter can be made using both the Timer_A modules on the MSP430G2553, but guess my first question is this possible the way I am attempting to do it, by also generating the PWM from the MSP430?

TimerA_0 is used for the PWM generation on P1.2

TimerA_1 is used to generate an interrupt every ~500mS this is to allow some further code to be added for calculation and displaying later.  GPIO P1.2 is looped to P2.1 and CCI1A is used to capture the incoming pulses.

The problem is I have the frequency of the PWM set quite low (250Hz) so it's possible to see the Count variable is approximately right, when pausing and running the code.  However the captured value is way too high and not consistent with the PWM signal connected, if I ground P2.1 the Count variable stays at zero.  I have checked the PWM with an oscilloscope and know that its fine, so pretty sure I have misunderstood the timer operation despite re-reading the family guide timer section a few times.

Now at the stage where 'I can't see the wood for the trees', so after someone to just say not possible and I can then pursue another route with a 555 timer as a make shift external square wave generator for testing.

#include <msp430g2553.h>

volatile unsigned int Count = 0;
volatile unsigned int Result = 0;

int main(void) {

	/*** Watchdog timer and clock Set-Up ***/
	WDTCTL = WDTPW + WDTHOLD;		// Stop watchdog timer
	DCOCTL = 0;             		// Select lowest DCOx and MODx
	BCSCTL1 = CALBC1_1MHZ + DIVA_1;  		// Set range
	//BCSCTL3 |= LFXT1S_2;  // VLO mode
	DCOCTL = CALDCO_1MHZ;   		// Set DCO step + modulation


		// Set-up GPIO
		P1DIR |= BIT2;					// P1.2 set as output
		P1SEL |= BIT2;					// P1.2 selected Timer0_A Out1
		P2DIR &= ~BIT1;					// P2.1 set as input
		P2SEL |= BIT1;					// P2.1 selected Timer1_A CCI1A

		// PWM Output P1.2
		TA0CCR0 |= 500 - 1;					// PWM Period ~250Hz
		TA0CCTL1 |= OUTMOD_7;				// TA0CCR1 output mode = reset/set
		TA0CCR1 |= 250;						// TA0CCR1 PWM duty cycle 50%
		TA0CTL |= TASSEL_2 + MC_1 + ID_3;	// SMCLK, Up Mode (Counts to TA0CCR0), /8

		// PWM Capture P2.0
		TA1CCR0 = 62500;						// SMCLK 1MHz/8 = 125kHz therefore interrupt every ~500mS
		TA1CCTL0 |= CCIE;						// Capture/compare interrupt enable
		TA1CCTL1 |= CM_1 + CCIS_0 + CAP + CCIE;	// Falling Edge, CCI1A as input, Capture mode, Int enable
		TA1CTL |= TASSEL_2 + MC_1 + ID_3;		// SMCLK, Continous. /8

    _BIS_SR(GIE);		// interrupts enabled

}

//Timer_A1 TACCR0 Interrupt Vector Handler Routine
#pragma vector=TIMER1_A0_VECTOR
__interrupt void Timer1_A0(void)
{
	Result++;
//	Result = Count;
//	Count = 0;
}

//Timer_A1 TACCR1 Interrupt Vector Handler Routine
#pragma vector=TIMER1_A1_VECTOR
   __interrupt void Timer1_A1 (void)
{
	Count++;
	TA1CTL &= ~TAIFG;		// Clear the interrupt flag
}

Thanks,

Ant

  • Ant,

    a few things I get from the first sight - this one:

    TA0CCR0 |= 500 - 1;

    only works when TA0CCR0 was zero before (which might be the case), but in general I would prefer the "=" for it. Furthermore there is missing "the main program", so you should set the controller into sleep mode or add

    while( 1 ) {}

    at the end of your main().

    Dennis

  • Hi Dennis,

    Thanks I missed the TA0CCR0 and have amended, I had tried a low power mode and While already but had no effect, will ensure one is implemented for further testing though.

    Ant

**Attention** This is a public forum