Myst3ry 0 Posted December 23, 2010 Share Posted December 23, 2010 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 } Quote Link to post Share on other sites
jsolarski 94 Posted December 23, 2010 Share Posted December 23, 2010 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. Quote Link to post Share on other sites
jsolarski 94 Posted December 23, 2010 Share Posted December 23, 2010 I forgot to mention, My WDT PWM code could work for you, with Timer_A, just look in the projects for it. Edit LOL instead of trying my code, try a variation of this one http://www.43oh.com/forum/viewtopic.php?f=9&t=284&p=2208#p2208 Quote Link to post Share on other sites
Myst3ry 0 Posted December 23, 2010 Author Share Posted December 23, 2010 I saw your code, but if i dont use for loop, how am i surpose to make it run in orderly manner of 50% den 40% den back to 50% , 40% etc etc. Quote Link to post Share on other sites
Myst3ry 0 Posted December 23, 2010 Author Share Posted December 23, 2010 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 } Quote Link to post Share on other sites
RobG 1,891 Posted December 23, 2010 Share Posted December 23, 2010 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. Quote Link to post Share on other sites
jsolarski 94 Posted December 23, 2010 Share Posted December 23, 2010 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 Quote Link to post Share on other sites
RobG 1,891 Posted December 23, 2010 Share Posted December 23, 2010 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... Quote Link to post Share on other sites
jsolarski 94 Posted December 23, 2010 Share Posted December 23, 2010 You are correct RobG. FYI the code that i posted is not meant to be copy pasted and copied. Quote Link to post Share on other sites
Myst3ry 0 Posted December 27, 2010 Author Share Posted December 27, 2010 Thanks guys, btw i got it all wrong program pwm 1khz , 50% , 40% this is what is requested . Any 1 could help? Quote Link to post Share on other sites
jsolarski 94 Posted December 27, 2010 Share Posted December 27, 2010 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 Quote Link to post Share on other sites
Myst3ry 0 Posted December 28, 2010 Author Share Posted December 28, 2010 i've tried to change it. but it seems that it is only showing 50% on the scope. the requested outcome should be shown on the scope is this : Quote Link to post Share on other sites
jsolarski 94 Posted December 28, 2010 Share Posted December 28, 2010 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. Quote Link to post Share on other sites
RobG 1,891 Posted December 28, 2010 Share Posted December 28, 2010 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; } } Quote Link to post Share on other sites
jsolarski 94 Posted December 28, 2010 Share Posted December 28, 2010 @Myst3ry what chip are you using? And are you using Timer_A or Timer_B? Sorry RobG for missing that lol, Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.