Jump to content
Sign in to follow this  
Myst3ry

PWM codes and TimerA

Recommended Posts

Hi Guys,

 

I have an enquiry, Why doesnt it get the interupt in the for loop?

 

My intention is to allow 50% after a cycle and 40% after that. and Continuously 50% , 40%.

 

My codes look like this:

 

 

#include "msp430x22x4.h"

 

void main(void)

{

 

WDTCTL = WDTPW + WDTHOLD; // Stop WDT

TACCTL0 = CCIE;

TACTL = TASSEL_2 + MC_1; // TACLK = SMCLK, Up mode.

P4DIR |= 0x20; // P4.5 output

P4SEL |= 0x20; // P4.5 TBx options

 

for(;;)

{

TBCCR0 = 512 - 1; // PWM Period

TBCCTL2 = OUTMOD_7; // TBCCR2 reset/set

TBCCR2 = 256; // TBCCR2 PWM duty cycle, 50%

TBCTL = TBSSEL_2 + MC_1; // SMCLK, up mode

__bis_SR_register(GIE);

}

 

 

}

#pragma vector=TIMERA0_VECTOR

__interrupt void Timer_A (void)

{

TBCCR0 = 512 - 1; // PWM Period

TBCCTL2 = OUTMOD_7; // TBCCR2 reset/set

TBCCR2 = 205; // TBCCR2 PWM duty cycle, 40%

TBCTL = TBSSEL_2 + MC_1; // SMCLK, up mode

}

Share this post


Link to post
Share on other sites

Well there are a few things that need to be corrected. what was correct is when you first setup the PWM with Timer_A, and how you call the interrupt. Putting your timer setup code into the interrupt will not work, because every time it returns from the interrupt it will reset your settings in the for loop and i think certain registers you have to call a special way to change the value (within the interrupt) but i may be wrong.

Share this post


Link to post
Share on other sites

I've modify it and now i have a problem geting it back to 50%

 

#include "msp430x22x4.h"
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P4DIR |= 0x20; // P4DIR = P4DIR | 0x20 set P4.5 output
P4SEL |= 0x20; // P4.5 TBx options
TACCTL0 = CCIE; // TACCR0 interrupt enabled
TACCR0 = 37500; // set value of compare register to 37500 to achieve 1sec blinking rate
TACTL = TASSEL_2 + MC_3 + ID_3 ; // SMCLK, Up/Down Mode

for(;
{
         TBCCR0 = 512 - 1; // PWM Period
         TBCCTL2 = OUTMOD_7; // TBCCR2 reset/set
         TBCCR2 = 16; // TBCCR2 PWM duty cycle, 2%
         TBCTL = TBSSEL_2 + MC_1; // SMCLK, up mode
         __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
}
}

// Timer A0 interrupt service routine
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{

         TBCCR0 = 512 - 1; // PWM Period
         TBCCTL2 = OUTMOD_7; // TBCCR2 reset/set
         TBCCR2 = 406; // TBCCR2 PWM duty cycle, 2%
         TBCTL = TBSSEL_2 + MC_1; // SMCLK, up mode

}

Share this post


Link to post
Share on other sites

Why don't you just toggle it in the interrupt?

 

This part should be executed only once, put it in the main

TBCCR0 = 512 - 1; // PWM Period
         TBCCTL2 = OUTMOD_7; // TBCCR2 reset/set
         TBCTL = TBSSEL_2 + MC_1; // SMCLK, up mode

 

Get rid of for, then in the interrupt routine, use if statement to toggle duty cycle

if(toggle ^= 1) {
TBCCR2 = DUTY_1;
} else {
TBCCR2 = DUTY_2;
}

 

One more question, why are you using two timers?

You have interrupt for timer A, but changing CCR on timer B.

Share this post


Link to post
Share on other sites

You would want some thing like this

 

#include "msp430x22x4.h"
int counter = 0;
void main(void)
{

WDTCTL = WDTPW + WDTHOLD; // Stop WDT
TACCTL0 = CCIE;
TACTL = TASSEL_2 + MC_1; // TACLK = SMCLK, Up mode.
P4DIR |= 0x20; // P4.5 output
P4SEL |= 0x20; // P4.5 TBx options
TBCCR0 = 512 - 1; // PWM Period
TBCCTL2 = OUTMOD_7; // TBCCR2 reset/set
TBCCR2 = 256; // TBCCR2 PWM duty cycle, 50%
TBCTL = TBSSEL_2 + MC_1; // SMCLK, up mode
__bis_SR_register(GIE);



}


#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{

if (counter==0) [
//TBCCR0 = 512 - 1; // PWM Period
//TBCCTL2 = OUTMOD_7; // TBCCR2 reset/set
BCCR2 = 205; // TBCCR2 PWM duty cycle, 40%
//TBCTL = TBSSEL_2 + MC_1; // SMCLK, up mode
}//end if
if (counter == 1) {
counter = 0;
//TBCCR0 = 512 - 1; // PWM Period
//TBCCTL2 = OUTMOD_7; // TBCCR2 reset/set
TBCCR2 = 256; // TBCCR2 PWM duty cycle, 50%
//TBCTL = TBSSEL_2 + MC_1; // SMCLK, up mode
}// end if 

}//end interrupt


 

the settings will toggle during the interrupt, I do not know if this will work since i havent tested it, but you want something similar to this

Share this post


Link to post
Share on other sites

TBCCR0 = 512 - 1; // PWM Period
TBCCTL2 = OUTMOD_7; // TBCCR2 reset/set
TBCTL = TBSSEL_2 + MC_1; // SMCLK, up mode

the above lines are redundant in your interrupt routine (plus they only need to be executed once) and I am not sure but they may affect the timer.

I would remove them from interrupt and put the just before __bis_SR...

Share this post


Link to post
Share on other sites

what you need to do is choose your clock source, then 1/clocksource(in hertz) = total time for one clock cycle, this is needed to calculate how many clock cycles will be needed for 1kHz speed. to calculate from there you want to do .001/total time for 1 clock cycle. So you will need to have about 1000 clock cycles for you to get to 1KHz. then 40% and 50%.

you will need to set TBCCR0 with your PWM period (1000, i think) and TBCCR2 with 400 for 40% and 500 for 50%.......the rest of the code that we have helped you with is still valid

 

 

CCR0 = (1/ CLKsrc) x (1/hertz for your period) = 1000 for 1Khz PWM period

CCR1 = % of CCR0 = 400 for 40% and 500 for 50%

 

you may want to double check my calulations

Share this post


Link to post
Share on other sites

try this

#include "msp430x22x4.h"
int counter = 0;
void main(void)
{

WDTCTL = WDTPW + WDTHOLD; // Stop WDT
TACCTL0 = CCIE;
TACTL = TASSEL_2 + MC_1; // TACLK = SMCLK, Up mode.
P4DIR |= 0x20; // P4.5 output
P4SEL |= 0x20; // P4.5 TBx options
TBCCR0 = 1000; // PWM Period
TBCCTL2 = OUTMOD_7; // TBCCR2 reset/set
TBCCR2 = 500; // TBCCR2 PWM duty cycle, 50%


__bis_SR_register(GIE);
}


#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{

switch(counter) {
        case 0:  //case to have a 40% duty cycle
                 counter = 1;  //toggles counter to 50% when the next time it runs 
                 TBCCR2 =400; // TBCCR2 PWM duty cycle, 40%
                 break; //breaks out of switch so there is no endless loop
        case 1: //case for 50 % 
                counter = 0; //resets count back to 40%
                TBCCR2 =500; // TBCCR2 PWM duty cycle, 50%
                 break; //breaks out of the switch
} // end of switch
} //end of interrupt

hopefully this will work for you.

Share this post


Link to post
Share on other sites

Your problem is that you are mixing two timers, TimerA and TimerB.

 

I don't have MCU you are using, so I show you the code for g2231 that does what you need.

#include "msp430g2231.h"
unsigned int toggle = 0;
void main(void)
{
 WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

 P1DIR |= BIT2;					 
 P1SEL |= BIT2;                            // P1.2 TA1 option select

 TACCTL0 = CCIE;
 TACCR0 = 1000;
 TACCTL1 = OUTMOD_7;
 TACCR1 = 500;
 TACTL = TASSEL_2 + MC_1 + ID_0;

__bis_SR_register(GIE);
}


#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{	
if(toggle ^= 1) {
	TACCR1 = 500;
} else {
	TACCR1 = 400;
}
}

 

Your code should look something like this:

#include "msp430x22x4.h"

unsigned int toggle = 0;

void main(void)
{

WDTCTL = WDTPW + WDTHOLD; // Stop WDT

P4DIR |= 0x20; // P4.5 output
P4SEL |= 0x20; // P4.5 TBx options

TBCCTL0 = CCIE;
TBCCR0 = 1000; // PWM Period
TBCCTL2 = OUTMOD_7; // TBCCR2 reset/set
TBCCR2 = 500; // TBCCR2 PWM duty cycle, 50%
TBCTL = TBSSEL_2 + MC_1; // SMCLK, up mode
__bis_SR_register(GIE);
}

#pragma vector=TIMERB0_VECTOR
__interrupt void Timer_B (void)
{
if(toggle ^= 1) {
	TBCCR2 = 500;
} else {
	TBCCR2 = 400;
}
}

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...