SLAA513B December   2011  – February 2022 MSP430G2112 , MSP430G2112 , MSP430G2152 , MSP430G2152 , MSP430G2212 , MSP430G2212 , MSP430G2252 , MSP430G2252 , MSP430G2312 , MSP430G2312 , MSP430G2352 , MSP430G2352 , MSP430G2412 , MSP430G2412 , MSP430G2452 , MSP430G2452

 

  1.   Trademarks
  2. 1Typical Single Time Base Method
  3. 2Multiple Time Base Method
  4. 3Implementing the Multiple Time Base Method in a Custom Application
    1. 3.1 Timer Clock Source Selection
    2. 3.2 Period and Frequency Calculation
    3. 3.3 Duty Cycle Calculation
  5. 4Example Code
    1. 4.1 Method
      1. 4.1.1 ISR for Multiple Frequencies
      2. 4.1.2 ISR for Multiple Frequencies and Duty Cycles (PWM)
    2. 4.2 Included Code Examples
  6. 5Limitations of the Multiple Time Base Method
    1. 5.1 ISR Overhead
    2. 5.2 Maximum Output Frequency vs Number of Signals
    3. 5.3 Power Consumption
  7. 6References
  8. 7Revision History

ISR for Multiple Frequencies and Duty Cycles (PWM)

For implementing multiple duty cycles as well as frequencies on a single timer module, the timer ISRs become slightly more complex. After determining which TxCCRx count triggered the interrupt, we must also determine whether the output is entering the high or low portion of the signal output so that we know whether to add the count corresponding to the high or low time. This can be done by checking the CCI bit in the corresponding TxCCTL0 register. If the CCI bit is 1, then we know that the output just toggled to high, the signal is at the beginning of the high cycle, so we must add the count corresponding to the high time. Conversely, if the CCI bit is 0, the output just toggled to low, and we must add the count corresponding to the low time. The sum of the counts corresponding to the high and low times determines the period of the signal, and the ratio of the high and low times to the period value determines the duty cycle. The following code shows the timer ISRs from the file multi_freq_g2452_pwm_example.c:

// Timer_A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0 (void)
{
    if(TACCTL0 & CCI)                         // If output currently high
    {
        TACCR0 += 50;                         // 25% high
    }
    else
    {
        TACCR0 += 150;                        // 75% low
    }
}
// Timer_A1 Interrupt Vector (TA0IV) handler
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A1(void)
{
  switch( TA0IV )
  {
  case  2:  if(TACCTL1 & CCI)                 // If output currently high
            {
                TACCR1 += 50;                 // 12.5% high
            }
            else
            {
                TACCR1 += 350;                // 87.5% low
            }
           break;
  case  4:  if(TACCTL2 & CCI)                 // If output currently high
            {
                TACCR2 += 600;                // 60% high
            }
            else
            {
                TACCR2 += 400;                // 40% low
            }
           break;
  case 10: P1OUT ^= 0x01;                   // Timer overflow
           break;
  default: break;
  }
}

In this case, the code generates the same frequencies of 5-kHz, 2.5-kHz, and 1-kHz signals from a 1-MHz timer clock source. However, this time the signals have 25%, 12.5%, and 60% duty cycles respectively (see Equation 5).

Equation 5. GUID-193E9597-D1A4-4466-98F2-D3FFE8A272C5-low.gif