PWM using TimerB in continuous mode

Hello Friends/Members,

I am using MSP430F2418 device and want to generate the PWM on pin TB5 using

continuous mode of TimerB. I am using this timer - module 4 and module 6 - for

two different timeout values. I want to generate a PWM of 50% duty cycle and a

period of 150Hz using module 5 which in turn will output a PWM on TB5. I am

using ACLK=1MHz. Below is the code, I have written to configure TimerB and

corresponding modules:

void Init_TimerB (void)

{

TBCTL = (TBCLR | MC_0); //Individual compare latch / Clear TimerB / Stop

TimerB

TBCTL = (CNTL_0 | TBSSEL_1 | ID_1); //16bit / ACLK / Divide by 2 / Stop

TBCTL &= ~(TBIE | TBIFG); //Disable TBIV and flag

TBCTL = (CNTL_0 | TBSSEL_1 | ID_1 | MC_2); //16bit / ACLK / Divide by 2 /

Continuous

}

void ConfigTimerB4_Timeout (UINT tout)

{

TBCCTL4 &= ~CCIE; //Disable interrupt

TBCCTL4 &= ~CAP; //Compare mode

//CM_0 = No Capture

//CCIS_1 = Capture/Compare input is TB4

//SCS = Synchronous capture

//CLLD_0 = Load compare latch (TBCLx) when TBCCRx

is written

//OUTMOD_0 = output value of OUT on pin

//CCIE = Enable interrupt

//OUT = Output high on pin

TBCCTL4 = (CM_0 | CCIS_1 | SCS | CLLD_0 | OUTMOD_0 | CCIE | OUT);

TBCCR4 = (TBR + tout);

}

void ConfigTimerB6_Timeout (UINT tout)

{

TBCCTL6 &= ~CCIE; //Disable interrupt

TBCCTL6 &= ~CAP; //Compare mode

//CM_0 = No Capture

//CCIS_1 = Capture/Compare input is TB6

//SCS = Synchronous capture

//CLLD_0 = Load compare latch (TBCLx) when TBCCRx

is written

//OUTMOD_4 = Toggle TB6

//CCIE = Enable interrupt

//OUT = Output high on pin if OUTMOD_0

TBCCTL6 = (CM_0 | CCIS_1 | SCS | CLLD_0 | OUTMOD_4 | CCIE | OUT);

TBCCR6 = (TBR + tout);

}

void ConfigTimerB5_PWM (void)

{

P4SEL &= ~0xA0;

P4SEL |= 0x20; // P4.5 - Select as TB5 functionality

P4DIR |= 0x20; // P4.5 - Select compare as output

TBCCR0 = 0;

TBCCTL5 &= ~CCIE; //Disable interrupt

TBCCTL5 &= ~CAP; //Compare mode

//CM_0 = No Capture

//CCIS_1 = Capture/Compare input is TB4

//SCS = Synchronous capture

//CLLD_0 = Load compare latch (TBCLx) when TBCCRx is

written

//OUTMOD_0 = output value of OUT on pin

//CCIE = Enable interrupt

//OUT = Output high on pin

TBCCTL5 = (CM_0 | CCIS_1 | SCS | CLLD_0 | OUTMOD_3 | CCIE | OUT);

TBCCR5 = (1660);

}

I am not sure of module 5 configuration. Please guide me to get the PWM in continuous mode. If I use UP mode for timer, then I am able to generate the PWM properly but failing to get required timeouts. Is it possible to use timer either in Up or Continuous mode to generate both PWM as well as timeouts? Please help me for this. Your earliest help in this regard will be highly appreciated. Thanks in advance.

I think you can set TACCTL5=0x0090;

In the corresponding ISR, you do TACCR5 += 1667;

Thanks OldCow for your reply.!!

Doing this and trying other options for OUTMOD bits also is not working. Does anyone have solution for this? I really need the same very much as project work is held up. I request all forum members for the same. Thanks in advance.

Do you know which pin is able to output OUT5 signal from TB?

Did you set up that pin to do so?

The TB5 - P4.5 outputs the signal. I have configured the same as,

P4SEL |= 0x20; // P4.5 - Select as TB5 functionality

P4DIR |= 0x20; // P4.5 - Select compare as output

Are anyother settings required?

#include "msp430.h"
#define UINT unsigned int
#include "your_posted_code.txt"
void main( void )
{
  WDTCTL = WDTPW + WDTHOLD;
  
  //Set up your ACLK here
  ... ??? ...

  //Call your routines
  Init_TimerB();
  ConfigTimerB4_Timeout (12345);
  ConfigTimerB6_Timeout (54321);

  //But do not use your ConfigTimerB5_PWM();
  //Use the following instead
  P4OUT &= ~0x20;
  P4DIR |= 0x20;
  P4SEL |= 0x20;
  TBCCTL5 = 0x90;
  
  //Enable GIE
  _BIS_SR(GIE);
  
  while (1)
  {
    //Let TimerB do its job
    //Do not turn off the power
    //Do not reset the system
    //Do not disable interrupts
    //Do not change ACLK
    //Do not change TimerB
    //Do anything else, or nothing at all
  }
}

#pragma vector = TIMERB1_VECTOR
__interrupt void TB_ISR( void )
{
  switch (TBIV)
  {
  case 8: break;  //ISR for your TB4
  case 12: break; //ISR for your TB6
  case 10:        //ISR for TB5
    {
      TBCCR5 += 1667;
      break;
    }
  }
}

Thanks OldCow. This seems to be working for PWM. I will integrate this in my code and will check. I have some queries here. Please have some time to clarify those.

  1. We have not initialised the TBCCR0 which will be PWM period. why this is not needed?

  2. You have asked not to disable interrupts in main loop. Whether disabling and enabling of interrupts will cause this PWM generation in anyway?

  3. What is wrong with the ConfigTimerB_PWM routine? Whether TBCCR0 initialisation?

Thanks in advance. Please answer the queries.

The code I posted yesterday was based on:

I think you can set TACCTL5=0x0090;

In the corresponding ISR, you do TACCR5 += 1667;

Your ConfigTimerB_PWM routine could work too. But the ISR needs to be:
{
  TBCCR0 = TBCCR5 + 1667;
  TBCCR5 += 3333;
}

Thanks once again OldCow. I did the TBCCTL5 = 0x0090; but TBCCR5 was updated elsewhere in the code which instead should be in corresponding ISR.

Thanks again.

Hello Forum members,

I am now able to generate the PWM in continuous mode and can vary the PWM duty cycle from 0% to 100%. Here I have observed that the PWM duty cycle deviates to 100% at lower values i.e. at 0 to 10%. Does anyone have observed the same? Does anyone have solution for the same? This happens at some regular interval. This interval instance could be the TBR overflow, but I am not sure. Does anyone has similar observation? Please provide me solution for this.

Thanks in advance.

When you use continues mode to generate PWM, you need ISR twice per period, once at the beginning of the pulse and once at the end. ISR execution time imposes a lower limit to both <pulse_width> and <period – pulse_width>. Using the double buffer may help, but there are still limits.

When you use up mode to generate PWM, you need ISR only when you try to change the period or the pulse_width. That is why people use up mode when possible.

Hello,

Using UP mode for PWM is the only solution for this? Is there any other way out for this?

Thanks in advance.

Only Up-mode and Up-down-mode do not need ISR to generate PWM.

Using Cont.-mode, you can use CCR0 to assist you (I think you did that). This way you only need to execute ISR once per period. You can also use the buffered load to make it less time critical. The limitation is has to be longer than the ISR execution time.