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.

Generate Timer Interrupt every second

Other Parts Discussed in Thread: MSP430F2274

Hi,

how can i generate an interrupt every second? i use the internal oscillator of the msp430f2274 and TimerA0...is the way i do it the best way?

void main(void)

  init_TimerA0();

 

  __bis_SR_register(/*LPM0_bits +*/ GIE);       // Enter LPM0, interrupts enabled

 

  while(1);

}

 

void init_TimerA0()

{

  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

  BCSCTL1 = CALBC1_8MHZ;                    // Set DCO

  DCOCTL = CALDCO_8MHZ;                     

 

  TACCTL0 = CCIE;                           // TACCR0 interrupt enabled

  TACCR0 = 10000;

  TACTL = TASSEL_2 + MC_2;                  // SMCLK, contmode

}

 

// Timer A0 interrupt service routine

#pragma vector=TIMERA0_VECTOR

__interrupt void Timer_A (void)

{

  static unsigned int delay = 0;

 

  if(delay >= 800)

  {

    delay = 0;

    timer_isr();

  }

  else 

  {

    delay++;

  }

 

  TACCR0 += 10000;                          // Add Offset to TACCR0

}

  • Gerald Stanje said:
    how can i generate an interrupt every second? i use the internal oscillator of the msp430f2274 and TimerA0...is the way i do it the best way?

    The MSP itself does not know about time, only about clock cycles.
    However, using the 8MHz calibration values, you cann assume 1 clock cycle to be nearly 1/8000000s.
    Getting a 1s interval is tricky, it means you'll have to count to 8000000.
    The timer can only count up to 65536.
    So a few tricks can be used.

    First, you can set up SMCLK to count with 1/8 of the DCO. This reduces cock speed to 1MHz. Then you can set up the tiemr to be clocked with 1/8 of SMCLK, leaving 125000Hz clock speed.
    Next, you can set up the timer to trigger an interrupt every 62500 timer ticks (using up mode and setting CCR0 to 62500). Then every 1/2 second an interrupt happens. Every second interrupt a second has passed (hence 'second interrupt' :) )

  • Thanks for the Info,

    But right now I count till 8000000 right and achieve 1 sec? The only disadvantage is a higher interrupt load...

    Is it allowed to change the SMCLK at runtime, how is SMCLK related to BCSTL1 and DCOCTL?

    BCSCTL1 = CALBC1_8MHZ;                    // Set DCO

    DCOCTL = CALDCO_8MHZ;   

    Gerald

  • Gerald Stanje said:
    But right now I count till 8000000 right and achieve 1 sec? The only disadvantage is a higher interrupt load...

    Yes. Instead of every 4.000.000 clock cycles, you have an interrupt every 10.000. But basically it is the same.

    Gerald Stanje said:
    Is it allowed to change the SMCLK at runtime

    Every time you want. But if it is used by some critical processes (such an an UART bit clock), it may have unwanted effects (e.g. disturbed send/receive). But it is perfectly valid to do so.

    Gerald Stanje said:
    how is SMCLK related to BCSTL1 and DCOCTL?

    BCSCTL1 and DCOCTL define the speed of the digitally controlle doscillator (DCO). In default configuraiton, teh DCOs output frequency is the SMCLK input frequency. Which may be divided down up to /8. YOu als can switch the SMCLK input to an external clock signal or a crystal, if attached. But the default is the DCO. However, this may be different on other MSP families (there the crystal may be the default).

  • I dont trigger things at the same time...so if i transfer data to the UART after the timer interrup...it should be fine if i change the  SMCLK at runtime like in the following table!?

    1.) Set SMCLK to 1 MHz

    2.) Set TimerA interrupt

    3.) TimerA interrupt called

    4.) Set SMCLK to 8 MHz

    5.) Read 1 Wire Interface

    6.) Transfer to UART

    goto 1


    SMCLK to count with 1/8 of the DCO...like this?

    void init_TimerA0()

    {

    DCOCTL = CALDCO_1MHZ;     // SMCLK = DCO = 1MHz
    BCSCTL1 |= DIVS_3;                  // SMCLK is DCOCLK/8 (125kHz if DCO=1MHz)

    TACCTL0 = CCIE;                           // TACCR0 interrupt enabled

    TACCR0 = 62500;

    TACTL = TASSEL_2 + MC_2;                  // SMCLK, contmode

    }

    what is BCSCTL2?

  • Gerald Stanje said:
    i transfer data to the UART after the timer interrup...it should be fine if i change the  SMCLK at runtime

    No. When you change SMCLK for the UART, it will affect your 1s-delay. During the UART transfer, SMCLK will be clocked 8 time shigher. So for this duration, the timer will also progress 8 times faster.
    You'll need to compensate it, e.g. by moving the point of the next timer interrupt for the 'excess pulses' that happened during the UART transfer.
    If you don't, the next timer interrupt will happen earlier than expected.

    However, MCLK and SMCLK are independent of each other, so if you only want the CPU to run fast during the interrupt execution, you can set MCLK to 8MHz while SMCLK still runs on 1MHz (8MHz/8).

    On some MSPs, ACLK can be sourced from the same DCO or crystal frequency, so you can have ACLK running on 1MHz, driving the timer, while MCLK and SMCLK run on 8MHz for UART timing and CPU. On the 2274 (and all of the 2x family), ACLK can only be sourced from XT1 while SMCLK only from XT2 or DCO.

  • but i could just stop the timer interrupt / reset the timer / adjust the speed of the timer after the UART transfer and after the 1 sec timer interrupt?

  • Gerald Stanje said:
    but i could just stop the timer interrupt / reset the timer / adjust the speed of the timer after the UART transfer and after the 1 sec timer interrupt?

    Sure. It just wouldn't be a 1-s timer anymore ina sense that it fires every second. It will fire 1 second after last reset. if that's okay for you, fine.
    If you want an interrupt every second (60 per minute, 3600 per hour), then it will be difficult if you mess with its clock temporarily.

**Attention** This is a public forum