# MSP430F2272: Timer B Capture giving shorter measures than the real ones

I'm using:

CCS V8
MSP430F2272
DSO-x 2024A Agilent oscilloscope

Trying to measure elapsed time between pulses with Timer B, Capture Mode.

My square wave source is at 50 kHz and my timer_b clock at 1 MHz (MCLK = 8MHz, SMCLK = 8MHz, ACLK = 1MHz)(code below)

P2DIR |= 0x08;
P2SEL |= 0x08;
TACTL = (TASSEL_1 | MC_1 | ID_1);
TACCR0 = 0x09;
TACCR1 = 0x05;
TACCTL1 = OUTMOD_6;


Source is as good as it could be... 50.001 kHz

P4DIR &= ~0x04;
P4SEL |= 0x04;
TBCTL   = (CNTL_0 | TBSSEL_1 | MC_2 | TBIE);
TBCCTL2 = (CM_1 | CAP |  CCIS_0 | CCIE | SCS);


To infer how many seconds have passed between events, the following formula is used:

(Over*65565 + Event_1 - Event_0)*0.000001

Where:
Over - Number of timer B overflows (how many times TBR has counted 0)
65565 - The size of TBR, defined by CNTL_0 bit
Event_1 - Value of TBR at the moment of the second event
Event_0 - Value of TBR at the moment of the first event

Below is presented my ISR:

__interrupt void Timer_B1(void)
{
switch( __even_in_range(TBIV,14) )
{
case  0: break;                          // No interrupt
case  2: break;                          // CCR1 not used
case  4:
TB_Pulse0 = TB_Pulse1;
TB_Pulse1 = TBCCR2;
TBCCTL2 &= ~CCIFG;
if(TB_Pulse0){
TBCTL = 0;
SendXBee |= TRUE;
}
break;
case  6: break;                          // CCR3 not used
case  8: break;                          // CCR4 not used
case 10: break;                          // CCR5 not used
case 12: break;                          // CCR6 not used
case 14:
TBCCTL0 &= ~COV;
if(TB_Pulse1)
OverFlo++;                  // overflow
break;
default: break;
}
}


As you can realize, from the code above, I'll only count timer overflows once the first event was been captured. When my second event is captured, timer b is turned off and I'll send data through UART.

My routine to send data, inside main, simply check the 'SendXBee', put all data through an XBee radio and reset 'Over', 'Event_1' and 'Event_0' variables.

Even this code looking fine (at least for me..) it does not work! Values read on the other radio give me measures about 1/10th of the real signal period.

Any suggestions? (Yeah!! stop working with embedded electronics.... just kidding)

Thanks everybody.

• You do not need to clear the interrupt flag after reading TBIV. The code assumes that the counter is never zero, which is not necessarily true. What are the values of TB_Pulse0/1? Are you sure that the CPU runs fast enough to handle all events? – CL. Mar 15 '19 at 14:32
• Can you verify that ACLK really is 1MHz, because on the MSP430's that I've used it is a low speed clock, typically 32kHz. Perhaps select SMCLK as the clock for the timers and divide it by 8. – Steve G Mar 15 '19 at 15:49
• CL, TB_Pulse values are about 1/10 of what it should be. Yes, CPU runs fast enough, 8MHz. Firstly, test were run with a source at 100 mHz. Even that gave me wrongly results. Steve, I changed my source signal from a wave generator to timer A PWM exactly to check my clock source. Timer A clock source is the same as timer B signal and, i saw that my PWM signal is stable and correct (50.001 kHz). – Jonny Quest Mar 16 '19 at 15:46

Just found a workaround!!

Inside my ISR, I just disable the interrupt request, instead of disabling the entire timer.

So the code became:

__interrupt void Timer_B1(void)
{
switch( __even_in_range(TBIV,14) )
{
case  0: break;                          // No interrupt
case  2: break;                          // CCR1 not used
case  4:
TB_Pulse0 = TB_Pulse1;
TB_Pulse1 = TBCCR2;
TBCCTL2 &= ~CCIFG;
if(TB_Pulse0){
TBCCTL2 &= ~CCIE;           //Not TBCTL = 0;
SendXBee |= TRUE;
}
break;
case  6: break;                          // CCR3 not used
case  8: break;                          // CCR4 not used
case 10: break;                          // CCR5 not used
case 12: break;                          // CCR6 not used
case 14:
TBCCTL0 &= ~COV;
if(TB_Pulse1)
OverFlo++;                  // overflow
break;
default: break;
}
}