This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
I am using MSP430g2553 Timer A and I try to create multiple PWM signals using Timer_A3 for controlling multiple fans.
I wrote the following timer initialization and interrupt routine.I used Timer0_A0, Timer0_A1 and Timer1_A1 interrupt vectors to implement the required PWM generation code supporting P3.4,P3.5 and P3.1. I have used TA0CCR0 to create a 1ms interrupt as my events creation timer. but I used TA0CCR1 and TA0CCR2 and TA1CCR1 to create my PWMs. But only P3.4/TA0.1 shows a PWM signal, I do not have any PWM signal on port P3.5/TA0.0 and P3.1/TA1.0. Your response is highly appreciated.
void timera_init(void){
// setup the timer
TA0CCR0 = MSEC_INTERVAL;
TA0CTL = TASSEL_2 + MC_2; // SMCLK, countmode
TA0CCTL0 = CCIE; // CCR0 toggle,CCR0 interrupt enabled
runTime.msec = 0;
runTime.days = 0;
//initialize timer TA0.0/P3.4 and TA0.1/P3.5 for PWM generation
TA0CCTL1 &=0x00;
TA0CCTL1 = OUTMOD_7+CCIE; // CCR1 toggle,CCR1 interrupt enabled
TA0CCTL2 = OUTMOD_7+CCIE; // CCR2 toggle,CCR2 interrupt enabled
//initialize timer TA1.0/P3.1
TA1CTL = TASSEL_2 + MC_2; // SMCLK, countmode
TA1CCTL0 &=0x00;
TA1CCTL0 = OUTMOD_7+CCIE; // CCR1 toggle,CCR1 interrupt enabled
//initialize the pins on port 3
P3DIR |= BIT1+BIT4+BIT5; // Set pin as output
P3SEL |= BIT1+BIT4+BIT5; // Select alternate function for PWM
}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
TA0CCR0 += MSEC_INTERVAL; // Add Offset to CCR0
runTime.msec++;
if (runTime.msec >= (long) 86400000) { // if we are at 24hours worth of msec
runTime.days++; // bump days
runTime.msec = (long) 0; // reset milliseconds
}
// turns off RS485 Transmit Enable when transmit buffer is empty and UART done with transmission
if((usart0_tx_buffer_count()==0) && !(UCA0STAT & UCBUSY)) {
P2OUT &= ~BIT7; // Turn off Transmit Enable to receive
}
}
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
{
switch(__even_in_range(TA0IV,14))
{
case 0: // CCR0
break;
case 2: // CCR1
#if 1
if(TA0CCTL1 & CCI) // If output currently high
{
TA0CCR1 += 200; // 60% high
}
else
{
TA0CCR1 += 600; // 40% low
}
#endif
break;
case 4: // CCR2
#if 0
if(TA0CCTL2 & CCI) // If output currently high
{
TA0CCR2 += 600; // 12.5% high
}
else
{
TA0CCR2 += 400; // 87.5% low
}
#endif
break;
default: break;
}
}
#pragma vector=TIMER1_A1_VECTOR
__interrupt void TIMER1_A1_ISR(void)
{
switch(__even_in_range(TA1IV,14))
{
case 0:
if(TA1CCTL0 & CCI) // If output currently high
{
TA1CCR0 += 600; // 12.5% high
}
else
{
TA1CCR0 += 400; // 87.5% low
}// CCR0
break;
case 2:
break;
case 4:
break;
}
}
HI
if you are genrating PWM signals ,use Timerx_A, comparel OUT1 or TimerX_A compare OUT 2 pins .I mean TA0.1 or TA0.2 or TA1.1 or TA1.2 you can only attach these pins to TA0CCR1 TA0CCR2 TA1CCR1 TA1CCR2 registers respectively.
Regards
Sri.
-------------------------------------------------------------------- please use verify answer if this answers you
It seems you msiunderstood a few things. You try to do PWM in software using the timer as interrupt generator for setting hte next output toggle point. This works, but not well (for DC near 0% or 100%, this may fail due to slow CPU execution comared to the required delay.
Also you use OUTMOD_7, which is reset/set mode. It resets the output on capture and sets it on timer overflow. YOu must change the OUT mode between set and reset mode for the next trigger point.
However, all this can be done by the hardware. You set the total PWM cycle time with CCR0 and operate the timer in up mode. This way, it will count from 0 to CCR0 and start again with 0.
Then OUTMOD_7 is the right choice. It sets the output automatically when the timer overflows to 0 and resets it when the timer counts to CCRx value. So CCRx directly defines the duty cycle. No need for any interrupt handling at all.
Also, you use the wrong port pins.
TA0CCR1 is on P3.5, TA0CCR2 is on P3.0 and P3.6 and TA1CCR1 is on P3.2
Hi Sri,
Thanks for your reply. I thought so too. Would please tell me why? According to Ti application note SLAA513, by putting the timer in a continuous we can program CCR0 also.
Regards,
Thanks Jens.
Q: If I change MC_2 (continuous mode) to MC_1 (Up mode) in my timera_init routine. Wouldn't that effect my event timer?
Q: Also if I set my FAN_PWM_PERIOD=800 counts(20KHZ based on MCLK of 16MHZ). Can I dynamically change values of TA0CCR1,TA0CCR2,TA1CCR1 and TA1CCR2 registers(i.e TA0CCR1=FAN_PWM_PERIOD-CURRENT_SPEED)
Regards,
Hi,
Hamid Khalessi said:we can program CCR0 also.
yes we can, u r trying to generate an o/p from pin tied to CCR1. TAxCCR1 = outmod_x + ccie will put the o/p wave form which has the capability of TAx.1 compare out 1 and so on.
Regards,
Sri.
Yes we can :) However, in this case you'll either have a PWM frequency based on the tiemr overflow cycle (65536 tiem rticks) or you'll have to constantly reprogram the CCRs, which may lead to looong times of PWM inactivity when you miss the right moment due to software latency. Especially on short duty cycles where oyu have only microseconds to act. Using CCR for limiting the timer cycle size (in up mode), you don't need to reprogram the other CCRs unless you want to change the duty cycle. If not, the PWM output is stable without any processor activity.Hamid Khalessi said:by putting the timer in a continuous we can program CCR0 also.
I must admit that the rather small timers on the G series make this a difficult decision. On other MSPs, a single timer has up to 7 CCR units.
**Attention** This is a public forum