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.

CCS/MSP430FR2355: Problems with timers

Part Number: MSP430FR2355

Tool/software: Code Composer Studio

Hi, I'm using msp430fr2355 and I'm trying to implement blocking delays in msec and usec with TB0. I need those to use lately in my code. 

When I delay in msec, the timer TB0 is sourced from SMCLK.

When I delay in usec, the timer TB0 is sourced from ACLK.

I want to implement two PWM using TB2 and TB3, both sourced from SMCLK.

I can have both pwms working with delay in ms, but when I change and use delay in usec, the pwm's frequencies change and also the delay. Why is that happening? What am I missing?

Here's my code:

uint16_t ms_counter;
uint16_t us_counter;


void delay_ms(uint16_t delay_ms)
{
    ms_counter = 0;
    TB0CCTL0 |= CCIE;                             // TBCCR0 interrupt enabled
    TB0CCR0 = 33;
    TB0CTL |= TBSSEL__ACLK | MC__UP;              // ACLK, continuous mode
    while(ms_counter != delay_ms);
    ms_counter = 0;
}

void delay_us(uint16_t delay_us)
{
    us_counter = 0;
    TB0CCTL0 |= CCIE;                             // TBCCR0 interrupt enabled
    TB0CCR0 = 24;
    TB0CTL |= TBSSEL__SMCLK | MC__UP;            // ACLK, continuous mode
    while(us_counter != delay_us);
    us_counter = 0;
}

void init_clock(void)
{
    /// Configure two FRAM waitstate as required by the device datasheet for MCLK
    // operation at 24MHz(beyond 8MHz) _before_ configuring the clock system.
    FRCTL0 = FRCTLPW | NWAITS_2 ;

    P2SEL1 |= BIT6 | BIT7;                       // P2.6~P2.7: crystal pins
    do
    {
        CSCTL7 &= ~(XT1OFFG | DCOFFG);           // Clear XT1 and DCO fault flag
        SFRIFG1 &= ~OFIFG;
    } while (SFRIFG1 & OFIFG);                   // Test oscillator fault flag

    __bis_SR_register(SCG0);                     // disable FLL
    CSCTL3 |= SELREF__XT1CLK;                    // Set XT1 as FLL reference source
    CSCTL0 = 0;                                  // clear DCO and MOD registers
    CSCTL1 |= DCORSEL_7;                         // Set DCO = 24MHz
    CSCTL2 = FLLD_0 + 731;                       // DCOCLKDIV = 24MHz
    __delay_cycles(3);
    __bic_SR_register(SCG0);                     // enable FLL
    while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));   // FLL locked

    CSCTL4 = SELMS__DCOCLKDIV | SELA__XT1CLK;   // set XT1 (~32768Hz) as ACLK source, ACLK = 32768Hz
                                                 // default DCOCLKDIV as MCLK and SMCLK source
}


void init_PWM_pins(void)
{
    // Configure GPIO
    //right PWM P5.0, left PWM P6.0
//    P1DIR |= BIT0 | BIT1 ;                          // set ACLK SMCLK pin as output
//    P1SEL1 |= BIT0 | BIT1;                          // set ACLK and  SMCLK pin as second function

    P5DIR |= BIT0;
    P5SEL0 |= BIT0;
    

    P6DIR |= BIT0;
    P6SEL0 |= BIT0;
    //Remember timer from SMCLK and SMCLK is set to 24MHz
    //Setup Timer3_B7 for P6.0
    TB3CCR0 = 1000-1;                                  // PWM Period
    TB3CCTL1 = OUTMOD_7;                              // CCR1 reset/set
    TB3CCR1 = 500;                                     // CCR1 PWM duty cycle

    //Setup Timer2_B3 for P5.0
    TB2CCR0 = 1000-1;                                  // PWM Period
    TB2CCTL1 = OUTMOD_7;                              // CCR1 reset/set
    TB2CCR1 = 500;                                     // CCR1 PWM duty cycle
//
    TB2CTL = TBSSEL_2 | MC_1 | TBCLR;                 // SMCLK, up mode, clear TBR
    TB3CTL = TBSSEL_2 | MC_1 | TBCLR;                 // SMCLK, up mode, clear TBR

}


int main(void)
{
    msg_received=0;
    //ms_counter_value = 0;
    WDTCTL = WDTPW | WDTHOLD;                         // Stop WDT

    P3DIR |= BIT6;
    P3OUT &= ~BIT6;

    init_clock();
    init_PWM_pins();

    PM5CTL0 &= ~LOCKLPM5;
    __enable_interrupt();

    while(1)
    {
        P3OUT ^= BIT6;
        delay_ms(1000);
        //__bis_SR_register(LPM3_bits | GIE);                     // Enter LPM3
    }
    //__no_operation();                                 // For debug
}


// Timer B0 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER0_B0_VECTOR
__interrupt void Timer_B (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_B0_VECTOR))) Timer_B (void)
#else
#error Compiler not supported!
#endif
{
    
    ms_counter++;
    us_counter++;
    
}

Thanks in advance!

Diana

  •     TB0CCR0 = 24;

    This is equivalent to 24 CPU clocks, which is not enough to run your timer ISR. (Estimate maybe 30-40 clocks for that.) As a result, the CPU will spend all of its time in the ISR, and main() won't run.

    I suggest you accept microsecond values, but actually count time in units of maybe 4 microseconds: (1) set CCR0=(4*24) and  (2) in the ISR use us_counter += 4; and (3) compare us_counter (in the while loop) using "<", not "!=".

    I don't see any obvious way this would affect the PWM output. How is your program different if you use delay_us?

    Unsolicited:

    > uint16_t ms_counter;
    > uint16_t us_counter;

    These should be declared "volatile". This may not be your trouble now, but it will be eventually.

  • Thank you very much for your answer, your suggestions solved the problem with the microsecond delay. PWMs are working well, I've probably made a mistake while measuring their frequency.

    Thanks again and regards,

    Diana

**Attention** This is a public forum