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.

MSP430F5529: To generate two delay functions without using Timer A or B but RTC_A

Part Number: MSP430F5529

Good evening, I have looked for a while to find out how to solve my issue, most probably is really easy to solve. But I couldn't find any similar problem till now.

Background: I am using all the 14 pwm outputs it means that al the TxxCCR0s are fixed to match the pwm periods.

The issue: I need to switch on the output with a delay time after a trigger command (that is fixed as input variable, so can't use __delay_cycle(xxx)), then the MCU lets the pwm ON, being able to attend USB interruptions and following the main program, but after period of time switch OFF the pwm outputs. So I need to measure two delays times that are gave by an user as a variables; first between the trigger and ON and second between ON and OFF. Both time are different each other and both can variate during the execution of the main software but non during the pwms operation.

I wanted to use RTC_A interruptions but I don't realize how to configure it in counter mode to do this two delays, they should be in order of hundreds of milliseconds and I'm using a SMCLK = 8Mhz.

I will be grateful if you can give me some ideas how to solve this thing without to do a loop that will generate some miss functions, in case messages from USB/CDC port could arrive and requiring som MCU activities.

Thank you

  • Section 22.2.1 of the User's Guide says:

    The clock to increment the counter can be sourced from ACLK, SMCLK, or prescaled versions of ACLK or SMCLK. Prescaled versions of ACLK or SMCLK are sourced from the prescale dividers (RT0PS and RT1PS). RT0PS and RT1PS output /2, /4, /8, 16, /32, /64, /128, and /256 versions of ACLK and SMCLK, respectively. The output of RT0PS can be cascaded with RT1PS. The cascaded output can be used as a clock source input to the 32-bit counter.

    Four individual 8-bit counters are cascaded to provide the 32-bit counter. This provides 8-bit, 16-bit, 24-bit, or 32-bit overflow intervals of the counter clock.

    If you configure both prescalers for /1, you get the 8 MHz clock into the 32-bit counter; an 8-bit overflow would then result in an interrupt interval of 256 / 8 MHz = 32 µs. By increasing one or both of the prescaler dividers, you can double this time repeatedly, up to about 2.1 s.

    If your desired delay does not match one of the times you can achieve (131/262/524/1049/2097 ms), you have to use a shorter interval, and count the number of interrupts.

  • Yes I checked the manual that explanation about how to use this real time clock as a counter is really small and you can find only one example also super basic in CCS cloud. I was seeking for something more flexible.

    Clemens Ladisch said:
    If your desired delay does not match one of the times you can achieve (131/262/524/1049/2097 ms), you have to use a shorter interval, and count the number of interrupts.

    Yes that's what I was trying to avoid is to be constrain need to have a counter variable and a If-else process in the interruption but do something like with the timers that you can modify the CCR0 and the fix a CCRx for the exactly delay time that you need, and perform only one action a time, due i need a generic way to modify those bounders, because i don't know in advance which time delays the user will choose, and with this dividers (prescale) looks like to strict. But well it looks like the more logical solution is to choose the smallest interruption interval and count till it reach the delay through a multiplier like

    delay = 32e-6*number_of_interruptions.

    Is it not possible to fix am interruption shorter than the overflow of 8 bits? in order to have an interruption every 10 or 20 us? in that case the multiple will be more rounded.

  • You can get any power-of-two multiple of 32 µs by reducing the prescaler dividers.

    (Hmm, calendar mode has alarm registers. But there is no alarm register for seconds, so with 8 MHz (running 244.14 times too fast), the minimum interval would be about 250 ms.)
  • Sorry I didn't about the minimum interval for 250 ms, what do you mean with 244.14 times too fast?

    I am re-checking all the manual and if I don't maid a mistake  i can have by example using SMCLK = 8MHz, three counters 1 equal 8 MHz and 2 of 4 MHz each, so for the first I can have an interruption every 32 us and for the others every 64 us, and masking them properly (it means not using them contemporaneously) I can have three handler of interruptions, now the problem is to know how long will be the process in side  each handler, it needs to be simple and fast to be execute before the next interruptions (32/64 us).

    ....
    #include "driverlib.h"
    ....
    RTC_A_initCounter(RTC_A_BASE, RTC_ACLOCKSELECT_SMCLK, RTC_A_COUNTERSIZE_8BIT);
    RTC_A_initCounterPrescale(RTC_A_BASE, RTC_A_PRESCALE_0, RTC_ACLOCKSELECT_SMCLK, RTC_A_PSDIVIDER_2);
    RTC_A_initCounterPrescale(RTC_A_BASE, RTC_A_PRESCALE_1, RTC_ACLOCKSELECT_SMCLK, RTC_A_PSDIVIDER_2);
    
    //as a function that receive a condition variable
    ...
    if(condition #1){
    RTC_A_clearIterrupt(RTC_A_BASE, RTCTEVIFG);
    RTC_A_holdClock(RTC_A_BASE);
    RTC_A_setCounterValue(RTC_A_BASE,0);
    RTC_A_enableInterrupt(RTC_A_BASE, RTCTEVIE);
    RTC_A_startClock(RTC_A_BASE);
    }else if (condition #2){
    RTC_A_clearIterrupt(RTC_A_BASE, RTC_A_PRESCALE_TIMER0_INTERRUPT);
    RTC_A_holdCounterPrescale(RTC_A_BASE, RTC_A_PRESCALE_0);
    RTC_A_setPrescaleValue(RTC_A_BASE, RTC_A_PRESCALE_0, 0);
    RTC_A_enableInterrupt(RTC_A_BASE, RTC_A_PRESCALE_TIMER0_INTERRUPT);
    RTC_A_startCounterPrescale(RTC_A_BASE, RTC_A_PRESCALE_0);
    }else{
    RTC_A_clearIterrupt(RTC_A_BASE, RTC_A_PRESCALE_TIMER1_INTERRUPT);
    RTC_A_holdCounterPrescale(RTC_A_BASE, RTC_A_PRESCALE_1);
    RTC_A_setPrescaleValue(RTC_A_BASE, RTC_A_PRESCALE_1, 0);
    RTC_A_enableInterrupt(RTC_A_BASE, RTC_A_PRESCALE_TIMER1_INTERRUPT);
    RTC_A_startCounterPrescale(RTC_A_BASE, RTC_A_PRESCALE_1);
    }
    
    .....
    //in interruption handler
    ....
    switch(__even_in_range(RTCIV,16))
    {
     case 0: break;
     case 2: break;
     case 4: //RTCEVIFG
            n_interruptions1++;
            if(n_interruptions1 == desideredValue1){
               RTC_A_disableInterrupt(RTC_A_BASE, RTCTEVIE);
               //do something
               brake;
            }
            brake;
     case 6: brake;
     case 8: //RT0PSIFG
            n_interruptions2++;
            if(n_interruptions2 == desideredValue2){
             RTC_A_disableInterrupt(RTC_A_BASE, RTC_A_PRESCALE_TIMER0_INTERRUPT);
             //do something else
             brake;
            }
            brake;
     case 10: //RT1PSIFG
             n_interruptions3++;
            if(n_interruptions3 == desideredValue3){
             RTC_A_disableInterrupt(RTC_A_BASE, RTC_A_PRESCALE_TIMER1_INTERRUPT);
             //do something else also
             brake;
            }
            brake;
      default: break;
    }
    .....//end of handler 

    I think something like this could work, but I am not completely sure especially  having those if process in the interrupt handler.

    Thank you for the patience, I know that the principal goal for RTC is to be used as a clock and not as a counter, but well this opportunity doesn't let me other choice.  

  • what do you mean with 244.14 times too fast?

    The RTC is designed for a 32.768 kHz crystal in calendar mode. 8 MHz / 32.768 kHz ≈ 244.14.

    You need to call RTC_A_definePrescaleEvent().

    Please note that you might not be able to handle interrupts that come too fast.

  • As i just increasing a counter most of the interruptions and if the verification becomes true stop further interruptions it worked well i got flexible delays and kind of accurate. Thanks for the guide.

**Attention** This is a public forum