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.

How to restart timer after stopping it ?

Hi everyone, I am having a problem in restarting the timer after stopping it. As you can see in the ISR, when i=12, I clear it and stop the timer by this line of code : TA0CTL &= MC_0; delay 100ms and then restart the timer by this line :TA0CTL |= MC_1. But I could only stop the timer and I couldn't restart it again. someone please help me. thank you very much.

‪#‎include‬ <msp430g2553.h>
#include "uart.h"

unsigned int i=0;
/*
* main.c
*/
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
//config clock
BCSCTL1 = CALBC1_16MHZ;
DCOCTL = CALDCO_16MHZ;

// config ngo ra ouput
P1SEL |= BIT6; // connect P1.6 to TA0.1
P1DIR |= BIT6; // P1.6 output

//config timer mode pwm
TA0CTL |= TASSEL_2 | MC_1; // SMCLK + up mode (count to TA0CCR0)
TA0CCTL0 |= CCIE; // enable interrupt when count to TA0CCR0
TA0CCTL1 |= OUTMOD_7; // output mode 7 (reset/set)
TA0CCR0 = 400; // TA0CCR0 = period of time
TA0CCR1 = 200; // TA0CCR1 = ON time (duty cycle)
_BIS_SR(GIE);
while(1);


}

‪#‎pragma‬ vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void){
i++;
if (i == 12) { // generate 12 burst 40Khz
i=0;
TA0CTL &= MC_0;
TAR=0;
__delay_cycles(1600000); // delay 100ms before send another 12 burst 40Khz

TA0CTL |=MC_1;
}
}


  • you have error in stop timer instruction:

    look,,,

    TA0CTL &= MC_0  -> TA0CTL &= 0x00  -> TA0CTL = 0x00

    so you setting TACTL on zero and you clearing you TA0 configuration
    if you want turn off timer up mode ( turn off you timer) you should use instruction

    TA0CTL &=~  MC_1;

    thats all,

  • So I don't understand why it also doesn't work when I write like this:

    if (i == 12) {	// generate 12 burst 40Khz
    i=0;
    TA0CTL &= 0xffcf;
    TAR =0;
    __delay_cycles(1600000);
    TA0CTL |=0xffdf;

  • You can not AND $0 in to turn a bit off, as MC_0 is a nothing value just to visually show that you want 0.

    > __delay_cycles(1600000);
    // delay 100ms before send another 12 burst 40Khz

    eew, why even bother with a C created delay (who knows what it uses)
    You are already in a timer IRQ.
    Use OUTMOD_0 (state of OUT Bit 2) or OUTMOD_5 (Reset) for 100ms while counter is still ticking away at 40khz 
     
    PS. you don't need to write 0 to TAR, include TACLR  when you write(restart) TA0CTL      
    Setting TACLR also clears the clock divider though      
     
    When the timer mode is either up or up/down, the timer may be stopped by writing 0 to TACCR0

  • Lukasz, for safe operation, I wouldn’t simply undo the assumed current operation mode. Sure, if MC_1 is active, an &=~MC_1 will switch to MC_0. But if MC_3 were active, it would unintentionally switch to MC_2 instead. So for all bitfields, masking the whole bitfield is the safest operation: TA0CTL &=~MC_3 (or 7, for bitfields with 3 bits etc.)
    Same for setting. TA0CTL |= MC1 will switch to MC_1, if the timer was stopped before. But if running on MC_2, it would activate MC_3 instead. So better mask correctly: TA0CTL = (TA0CTL&~MC_3)|MC_1;

    This is especially important for the timers, because the timer registers aren’t reset on a PUC (not even the IE bits!). The tiemrs continue to run as before the PUC. So if the WDT has caused a PUC while the timer was operating in UP mode, your freshly restarted program cannot switch it into CONT mode by a simple |=.

     Besides this, Tony is of course right with his remarks about the delay inside an ISR (and doubly so for a delay inside a timer ISR).
    And about the binary operations:
    Not only does &0x00 clear all bits (and &=~0x00 will do nothing at all), but the |= 0xFFDF sets plenty of bits that aren’t intended to be set. Including forcing an interrupt and switching the timer clock to the external INCLK.

  • Jens-Michael Gross said:
    Lukasz, for safe operation, I wouldn’t simply undo the assumed current operation mode. Sure, if MC_1 is active, an &=~MC_1 will switch to MC_0. But if MC_3 were active, it would unintentionally switch to MC_2 instead. So for all bitfields, masking the whole bitfield is the safest operation: TA0CTL &=~MC_3 (or 7, for bitfields with 3 bits etc.)
    Same for setting. TA0CTL |= MC1 will switch to MC_1, if the timer was stopped before. But if running on MC_2, it would activate MC_3 instead. So better mask correctly: TA0CTL = (TA0CTL&~MC_3)|MC_1;

    yes I know that saver is using

    TA0CTL &=~MC_3;   TA0CTL = (TA0CTL&~MC_3)|MC_1;

    but in my codes I always have full control of any bits  ;)

    and believe me for me is save using &=~MC_1  |=MC_1

  • Lukasz said:
    but in my codes I always have full control of any bits  ;)

    Well, if your projects start to grow larger, and you’re re-using modular code, things like that can lead to difficult to trace bugs. When multiple module share resources and don't know of each other.

**Attention** This is a public forum