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.

random time ACKL

Hello,

I need to clarify random time generation on MSP430. I use ACKL 32768 HZ.

assume i have random int each time:

void time(int random){

TA1CCTL0 = CCIE;
TA1CCR0 = random;
TA1CTL = TASSEL_1 + MC_1 + TACLR;

}

This counter should count until random and interrupt is generated. I want to know if I'm right or not:

random * 1 / 32768 = x seconds?

example: 32 * 1 / 32768 = 1 ms?? is right right?

Regards and thanks.

  • Fri_coder said:
    example: 32 * 1 / 32768 = 1 ms?? is right right?

    Well, it depends.

    ACLK is not necessarirly 32768Hz. It may be any frequency. On some MSPs (you don't write which one you have) it is zero (especially the 1x family) on startup, on 5x family, it is indeed 32768Hz (+-3%, sourced from REFO), on the others, well, it depends on clock system implementation.

    Assuming ACLK is indeed 32768hz, then each tick is 30.5µs. so after 32.768 ticks (rounded 33), one ms has passed.

    Note that you will get more than just one interrupt in regular intervals until you stop the timer or clear thr CCIE bit again.

  • Yes i'm using CC430f513f. I tried to implement that inside an interrupt ISR to get less than 1ms. However, the result is not correct. 

    count +=1;
    TA1CCR0 = 32768;

    if(count ==10){
    blink();
    count=0;
    }

    So the LED BLINK after 10 seconds?? What I'm doing wrong?

  • Fri_coder said:
    What I'm doing wrong?

    Several things (if thsi is indeed you code).

    Configuring an interrupt  causes the PCU to virtually insert a function call to an interrupt service function (ISR) in the current code execution.
    You need to write this ISR. nside the ISR you do the count++.

    Changing global variables from withing an ISR may go unnoticed by the main code, especially if you do a loop check on the variable. The compiler might have decided to make a temporary copy as the variabel is often read, ant then the change in memory to the variable, done by teh ISR, won't change the temporary code in the main code. To avoid this, such variables msu tbe declared volatile. This tells the compiler about possible side-effects when reading/writing the variable and avoids optiization.

    Last, your if must be enclosed into a loop. Else it will be checked only once and never again, so when teh 10 itnerrupts are passed, the main code is long done.

    How to write an ISR (and especially how to tell the compiler that it is an ISR and to which interrutp it belongs) is compiler dependent. So check the compiler manual.

  • Thank you for clarifying this issue,

    However the second part I didn't quit get it enclosing the code in a loop.

    here is the complite code with explanation:

    void TimerStart(void)
    {
         // Timer Inisialization
         TA1CCTL0 = CCIE;                          // CCR0 interrupt enabled
         TA1CCR0 = 32768;/                        // 32768
         TA1CTL = TASSEL_1 + MC_1 + TACLR;         // ACLK, upmode, clear TAR
    }

    count mode up until 32768 which equlas 30.5 us. After that Interrupt generated we call inside the ISR

    // Timer A0 interrupt service routine
    #pragma vector=TIMER1_A0_VECTOR
    __interrupt void TIMER1_A0_ISR(void)
    {
          count += 1;                           // every 30.5 us increment
     //    TA1CCR0 = 32768;            //  commented out
         

         if (count==10){           

              blink();
          
         }

        __bic_SR_register_on_exit(LPM3_bits); // Exit active
    }

    What I understood from this code and your explanation... if the code enters 10 times it means that every 30.5 us * 10 = 305 us LED will blink. However, I didn't understand why do I need the loop for?




  • Now the code makes a lot more sense.

    Now TimerStart configures the timer to generate an interrrupt after 32768 clock cycles. Which equals 32768*30.5µs = 1s.

    After 1s, teh CPU (assumed to be in LPM3) is awakened and sent to execute the timer ISR, which will increment the count. When teh count reaches 10, blink() is executed and the the MSP is configured to not return to LPM at ISR exit.

    Fri_coder said:
    I didn't understand why do I need the loop for?

    I didn't know that the count and if are inside the timer ISR. Then of course the 'loop' is generated by the interrupt.

    However, it is not a good idea to call any external functions from inside the ISR. At least it si inefficient, worst case the function may do something that won't work properly when inside an ISR (like enablign interrupts, or starting a hardware and waitinf for anotehr ISR to trigger and complete).

    An even worse idea is to do anything that includes waiting for an event. 'Blink' implies that you toggle a port and then wait and then toggle it back. the 'wait' part is a no-go inside an ISR.
    You rather should wake main and let it do the blink (you may signal the event through a global volatile variable). Alternatively you can do a state machine that start the blinking inside the ISR, reconfigures the timer and exits and in the next timer interrupt it continues the blink process. (the 'state' is stored in a global or static variable and tells the ISR what to do next)

**Attention** This is a public forum