MSP430 Timer Compare

From Texas Instruments Wiki
Jump to: navigation, search

The following wiki describes some aspects for working with MSP430 Timer A and B compare mode.

Timer Compare Basic Operation

Both Timer_A and Timer_B module of MSP430 can be operated in Compare mode to get the time of an compare input event by setting appropriate values of TAxCCTLy or TBxCCTLy (x=module number, y=CCR number) register.

There are basically two types of capture operations in Timer_A and Timer_B modules of MSP430:

  • Synchronous capture (SCS = 1)
  • Asynchronous capture (SCS = 0)

For the following explanations on how the two capture operations work in the timer modules, the following example code is used:

File:Tb compare test.zip

The example code comprises basically four tests:

  • TEST A: detecting pending CCIFG bit when the timer is operated in asynchronous capture mode
  • TEST B: detecting pending CCIFG bit when the timer is operated in synchronous capture mode
  • TEST C: similar to TEST B, but with workaround using reset_timer_b() function to avoid CCIFG get set when the timer is run
  • TEST D: detecting COV bit in asynchronous and synchronous capture mode

Synchronous capture

In synchronous capture mode, the timer capture is synchronized with the next input timer clock signal, i.e. the module needs to wait until the next timer clock signal before it will set the capture/compare interrupt flag (CCIFG) bit. This is the recommended operation mode to avoid the race condition which might occur in the asynchronous mode.

Setting CCIFG Bit in Synchronous Capture Mode

If the capture event is detected at the capture input pin while the timer is stopped (MC0 = MC1 = 0 -> no timer input clock), the timer module will not set the corresponding CCIFG bit immediately. Instead it will pend the interrupt flag until the timer input clock becomes available. This is shown by TEST B of the example code which can be found above.

The first part of the TEST B code tries to show whether the CCIFG bit is left in reset (0) when the event capture input occurs at the capture input pin since the timer is set in stop mode (MC0 = MC1 = 0).

  /******************************************************************************
 
    TEST B is for testing the synchronized capture (SCS = 1), showing that
    if the timer is stopped (MC0 = MC1 = 0) as the input capture pin
    catches the capture event, the CCIFG bit will be not directly set and the
    TBR content will be not copied into TBxCCR register.
    However the interrupt signal is pended due to synchronization with timer
    clock which is missing when the timer is stopped. The CCIFG flag will be set
    directly as soon as the timer is set to run due to the presence of timer
    clock.
 
    EXPECTED RESULTS: ccifg_set_test_b1 = 0 (CCIFG is not set)
                      ccifg_set_test_b2 = 1 (CCIFG is set)
 
  ******************************************************************************/
 
  // reset timer module
  reset_timer_b();
 
  // set Timer_B for capture at falling edge of TB1
  SETUP_TIMER_B(0xCAFE, // TBR
              0, // TBCCR
              CM_2 + CCIS_0 + SCS + CAP, // TBCCTL - synchronized capture
              0); // TBCTL - timer stop
 
  // try to invoke the interrupt using own GPIO - falling edge
  GENERATE_CAPTURE_SIGNAL_WITH_DELAY();
 
  // check if CCIFG is set
  if(CHECK_CCIFG())
  {
    ccifg_set_test_b1 = 1;
  }
  else
  {
    ccifg_set_test_b1 = 0;
  }
 
  // set breakpoint here if necessary to analyze the timer register
  // NOTE: CCIFG should not be set, TBxCCRy register stays as 0x0000
  //       ccifg_set_test_b1 should be 0
  __no_operation();

The second part shows how the timer module directly sets the pending CCIFG interrupt bit as soon as the timer is started in continuous mode.

  // now switch on timer in continuous mode
  SETUP_TIMER_B(0xCAFE, // TBR
              0, // TBCCR
              CM_2 + CCIS_0 + SCS + CAP, // TBCCTL - synchronized capture
              MC_2 + TBSSEL_2); // TBCTL - continuous mode, source SMCLK
 
  // test delay
  TEST_DELAY();
 
  // check if CCIFG is set
  if(CHECK_CCIFG())
  {
    ccifg_set_test_b2 = 1;
  }
  else
  {
    ccifg_set_test_b2 = 0;
  }
 
  // set breakpoint here if necessary to analyze the timer register
  // NOTE: CCIFG should be set, TBxCCRy register should be set as 0xCAFE
  //       ccifg_set_test_b2 should be 1
  __no_operation();

This condition where the CCIFG is suddenly set due to the pending capture event before the timer is activated might not be desired in certain application. One workaround for this might be to use the reset_timer_b() function in the example code before starting to run the timer.

/**************************************************************************//**
*
* reset_timer_b
*
* @brief     resetting timer pending flags
*
* @param     -
*
* @return    -
*
******************************************************************************/
void reset_timer_b(void)
{
  // resetting pending CCIFG interrupt and COV flag can be done by
  // letting the timer run and than clear the CCTL register
  TBCTL = MC_2 + TBSSEL_2; // set MC1 - continuous mode, source SMCLK
  TEST_DELAY();
  TBCCTL1 = 0; // clear CCTL register
  TBCTL = TBCLR; // timer clear & stop
 
  // delay
  __delay_cycles(100);
}


Setting COV Bit in Synchronous Capture Mode

The COV bit is used by the timer module as notification in case of overflow condition where a second timer capture event occurs before the first/previous capture event can be read through the CCIFG bit. When the timer is operated in synchronous mode, it is however possible to lost the overflow condition notification through COV bit if the capture event signal is faster than the timer clock. This is shown in the first part of the TEST D code above:

  /******************************************************************************
 
    TEST D is for testing the COV bit which should indicate the overflow
    condition set when a second capture event is received at the capture input
    pin prior the first/previous event is read out by the controller.
    However as can be seen in the result of previous tests, if the timer is
    operated in synchronous mode, the interrupt bit will be set synchronously
    with the input timer clock. When using a slow timer clock, capture event
    signal which is faster than the timer clock can cause the timer module
    to miss the overflow.
    If the timer is operated in unsynhronous mode, it shall be able to detect
    the overflow even if the event capture signal is faster than timer clock
 
    EXPECTED RESULTS: cov_set_test_d1 = 0 (COV is not set)
                      cov_set_test_d2 = 1 (COV is set)
                      cov_set_test_d3 = 1 (COV is set)
 
  ******************************************************************************/
 
  // reset timer module
  reset_timer_b();
 
  // set timer B module with slower clock
  SETUP_TIMER_B(0xCAFE, // TBR
              0, // TBCCR
              CM_2 + CCIS_0 + SCS + CAP, // TBCCTL - synchronized capture
              MC_2 + TBSSEL_2 + ID_3); // TBCTL - continuous mode, source SMCLK/8
 
  // generate capture event faster than timer clock
  GENERATE_CAPTURE_SIGNAL_WITHOUT_DELAY();
  GENERATE_CAPTURE_SIGNAL_WITHOUT_DELAY();
 
  // check if COV is set
  if(CHECK_COV())
  {
    cov_set_test_d1 = 1;
  }
  else
  {
    cov_set_test_d1 = 0;
  }
 
  // set breakpoint here if necessary to analyze the timer register
  // NOTE: COV bit should not be set, cov_set_test_d1 should be 0
  __no_operation();

In other case where the event capture signal is slower than the input timer clock, the COV bit is set as soon as the CCIFG is not yet read before the second event capture signal occurs. This is shown in the second part of the TEST D example code.

  // reset timer module
  reset_timer_b();
 
  // set timer B module with normal clock
  SETUP_TIMER_B(0xCAFE, // TBR
              0, // TBCCR
              CM_2 + CCIS_0 + SCS + CAP, // TBCCTL - synchronized capture
              MC_2 + TBSSEL_2); // TBCTL - continuous mode, source SMCLK
 
 
  // generate capture event slower than timer clock
  GENERATE_CAPTURE_SIGNAL_WITH_DELAY();
  GENERATE_CAPTURE_SIGNAL_WITH_DELAY();
 
  // check if COV is set
  if(CHECK_COV())
  {
    cov_set_test_d2 = 1;
  }
  else
  {
    cov_set_test_d2 = 0;
  }
 
  // set breakpoint here if necessary to analyze the timer register
  // NOTE: COV bit should be set, cov_set_test_d2 should be 1
  __no_operation();


Asynchronous capture

In asynchronous capture mode, the timer capture can occur asynchronously with respect to the input timer clock signal. The drawback of this capture operating mode is the possibility to get a race condition.

Setting CCIFG Bit in Asynchronous Capture Mode

As mentioned above, in asynchronous capture mode the timer capture event can occur asynchronously and independent of the timer clock. This means that even if the timer is operated in stop mode (MC0 = MC1 = 0), the CCIFG bit still can be set when the event capture signal is catched at the input pin. This is shown in TEST A in the example code above.

  /******************************************************************************
 
    TEST A is for testing the unsynchronized capture (SCS = 0), showing that
    although the timer is stopped (MC0 = MC1 = 0) as the input capture pin
    catches the capture event, the CCIFG bit will be directly set and the TBR
    content will be copied into TBxCCR register.
 
    EXPECTED RESULT: ccifg_set_test_a = 1 (CCIFG is set)
 
  ******************************************************************************/
 
  // reset timer module
  reset_timer_b();
 
  // set Timer_B for capture at falling edge of TB1
  SETUP_TIMER_B(0xCAFE, // TBR
              0, // TBCCR
              CM_2 + CCIS_0 + CAP, // TBCCTL - unsynchronized capture
              0); // TBCTL - timer stop
 
  // try to invoke the interrupt using own GPIO - falling edge
  GENERATE_CAPTURE_SIGNAL_WITH_DELAY();
 
  // check if CCIFG is set
  if(CHECK_CCIFG())
  {
    ccifg_set_test_a = 1;
  }
  else
  {
    ccifg_set_test_a = 0;
  }
 
  // set breakpoint here if necessary to analyze the timer register
  // NOTE: CCIFG should be set, TBxCCRy register should be set as 0xCAFE,
  //       ccifg_set_test_a should be 1
  __no_operation();

Setting COV Bit in Synchronous Capture Mode

Also for detecting overflow capture event through COV bit, in asynchronous mode this can be detected even if the signal is faster than the input timer clock. This is shown in the third part of TEST D.

  // reset timer module
  reset_timer_b();
 
  // set timer B module with slower clock
  SETUP_TIMER_B(0xCAFE, // TBR
              0, // TBCCR
              CM_2 + CCIS_0 + CAP, // TBCCTL - unsynchronized capture
              MC_2 + TBSSEL_2 + ID_3); // TBCTL - continuous mode, source SMCLK/8
 
  // generate capture event faster than timer clock
  GENERATE_CAPTURE_SIGNAL_WITHOUT_DELAY();
  GENERATE_CAPTURE_SIGNAL_WITHOUT_DELAY();
 
  // check if COV is set
  if(CHECK_COV())
  {
    cov_set_test_d3 = 1;
  }
  else
  {
    cov_set_test_d3 = 0;
  }
 
  // set breakpoint here if necessary to analyze the timer register
  // NOTE: COV bit should be set, cov_set_test_d3 should be 1
  __no_operation();