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.

Timer_B Using TB0.0 as PWM in Continuous Mode MSP430F5529

Other Parts Discussed in Thread: MSP430F5529

I am using a MSP430F5529 and I am trying to use PWM from Timer_B. I have no problem with PWM TB0,1 to TB0.6. In the documentation it says that when the timer is use in continuous mode, the compare latch TBCL0 works the same way as the other compare registers.

P7DIR |= GPIO_PIN5 + GPIO_PIN4;
P7SEL |= GPIO_PIN5 + GPIO_PIN4 ;
P7DS |= GPIO_PIN5 + GPIO_PIN4;
P5DIR |= GPIO_PIN6 + GPIO_PIN7;
P5SEL |= GPIO_PIN6 + GPIO_PIN7 ;
P5DS |= GPIO_PIN6 + GPIO_PIN7 ;

TB0CTL = TBCLGRP_0 + CNTL__12 + TBSSEL__SMCLK + MC__CONTINUOUS + ID__8 ;// 12 Bits, SMCLK, Continuous Counter, /8
TB0EX0 = TBIDEX__8; // Divide by 8
TB0CCR0 = 0x100 ;
TB0CCR1 = 0x400;
TB0CCR2 = 0x600;
TB0CCR3 = 0x800;
TB0CCTL0 = CLLD_0 + OUTMOD_7 ;
TB0CCTL1 = CLLD_0 + OUTMOD_7 ;
TB0CCTL2 = CLLD_0 + OUTMOD_7 ;
TB0CCTL3 = CLLD_0 + OUTMOD_7 ;

This is my code to test, it works fine when I comment TB0CCR0  and TB0CCTL0 . It is a self running PWM, no interrupt.

I am using: Code Composer V6 ; Compiler TI v4.3.4

  • Yes, in CONT mode, CCR0 acts the same way as all other CCRs. However, in CONT mode, the PWM period is controlled by the size of the timer counter register then.

    If you do not comment CCR0 and CCTL0, what happens? And what do you expect to happen?

  • When CCR0 and CCTL0 is commented everything works fine. When CCR0 and CCTL0 is active the frequency stay valid (equal to size of timer) but all the PWM ratio gets corrupted even the PWM0 does not math the compare value. I have tried different compare value and I cannot figure out the effect on the other PWM. 

  • Sorry, I have no idea what’s wrong.
    From the code you posted, I would expect the timer to cycle for 262144 SMCLK cycles (3.8Hz PWM frequency, assuming 1MHz clock).
    All outputs should go high simultaneously (TBR=0) and TB0.0 should stay on for 16384 clock ticks = 16ms, the others for 65, 98 and 131ms.

    Maybe it’s something else you do. Would you mind to post the complete code? Including all other inits or whatever happens after your PWM setup?
    Maybe it is something unrelated, like not triggering or disabling the watchdog, and the problem is the size/duration of the code rather than the code itself.

  • I made a standalone version to isolate the problem. I am using CCSv6.

    #include <msp430f5529.h>
    
    /*
     * main.c
     */
    int main(void) {
    
        WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    
        P7DIR |= BIT5 + BIT4;
        P7SEL |= BIT5 + BIT4 ;
        P7DS |=  BIT5 + BIT4;
        P5DIR |= BIT6 + BIT7;
        P5SEL |= BIT6 + BIT7 ;
        P5DS |=  BIT6 + BIT7 ;
    
        TB0CTL = TBCLGRP_0 + CNTL__12 + TBSSEL__SMCLK + MC__CONTINUOUS + ID__8 ;// 12 Bits, SMCLK, Continuous Counter, /8
        TB0EX0 = TBIDEX__8; // Divide by 8
        TB0CCR0 = 0xC00 ;
        TB0CCR1 = 0x600;
        TB0CCR2 = 0x800;
        TB0CCR3 = 0xA00;
        TB0CCTL0 = CLLD_0 + OUTMOD_7 ;
        TB0CCTL1 = CLLD_0 + OUTMOD_7 ;
        TB0CCTL2 = CLLD_0 + OUTMOD_7 ;
        TB0CCTL3 = CLLD_0 + OUTMOD_7 ;
    
        while ( 1 ) ;
    
    }
    

    Figure 1 - As per code (Freqency is 5Hz / 200 ms). PWM length is invalid.

    Figure 2 - TBCCR0 Set to Zero  (n.b. Ignore the Glitch, it is a bug on my oscilloscope.). Frequency is the same no mather the value in theTBCCR0 . The effect is the PWM Length.

    #include <msp430f5529.h>

    /*

    * main.c

    */

    int main(void) {

    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

    P7DIR |= BIT5 + BIT4;

    P7SEL |= BIT5 + BIT4 ;

    P7DS |= BIT5 + BIT4;

    P5DIR |= BIT6 + BIT7;

    P5SEL |= BIT6 + BIT7 ;

    P5DS |= BIT6 + BIT7 ;

    TB0CTL = TBCLGRP_0 + CNTL__12 + TBSSEL__SMCLK + MC__CONTINUOUS + ID__8 ;// 12 Bits, SMCLK, Continuous Counter, /8

    TB0EX0 = TBIDEX__8; // Divide by 8

    TB0CCR0 = 0xC00 ;

    TB0CCR1 = 0x600;

    TB0CCR2 = 0x800;

    TB0CCR3 = 0xA00;

    TB0CCTL0 = CLLD_0 + OUTMOD_7 ;

    TB0CCTL1 = CLLD_0 + OUTMOD_7 ;

    TB0CCTL2 = CLLD_0 + OUTMOD_7 ;

    TB0CCTL3 = CLLD_0 + OUTMOD_7 ;

    while ( 1 ) ;

    }

  • Form the scope shots, I can see now what you mean. With TBCCR0 set to anything, the output looks as if you had set the values to 0xa00, 0xc00 and 0xe00 instead of 0x600, 0x800 and 0xa00. It looks as if the second action, even though the timer is in cont mode, happens at TBR->TBCCR0 and not at TBR->0.

    So the rising edge you see in the first picture is not the timer overflow but rather TBR=0xc00.
    Personally, I never used any of the double-action modes together with CONT mode. But taking a second look at the users guide shows for OUTMODE_7
    “The output is reset when the timer counts to the TACCRx value. It is set when the timer counts to the TACCR0 value.” So this is exactly what you are observing. Being reset at 0x800 (TB0CCR1) and being set at 0xc00 (TB0CCR0).
    Still the statement that CCR= behaves like all others in cont mode is true: CCR0 is cleared at 0xc00 and set at 0xc00, which is a racing condition. This is why the users guide states mode 2,3,6 and 7 as not useful for CCR0. However, the internal logic delays the set to the next clock cycle, so CCR0 will expose a 1-cycle pulse. This info is found in the 3x users guide’s timer description, but my own experience shows that it is true for 1x family, and likely for all other families, since the timers haven’t changed much since.

**Attention** This is a public forum