Desired Delay using General Purpose Timers

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Desired Delay using General Purpose Timers

1,124 Views
kowshik700
Contributor I

Hello Expert Team,

I am using Keil uVision with NXP FRDM KL25Z for creating custom delays for my project using General Purpose timers. By using prescaler I am able to achieve a maximum delay of 5Hz. How can i control the delays? Please do tell me if I need to make any calculation with clock frequency in prior for setting up the MODULO register. You can view the sample code I wrote to light up an LED at an unknown but noticeable delay.

Labels (1)
Tags (1)
0 Kudos
3 Replies

882 Views
mjbcswitzerland
Specialist V

Hi

The TPM in the KL25 can be clocked from MCGIRCLK, OSCERCLK, MCGFLL or MCGPLLCLK/2 and your code sets it up to use MCGFLL, which is presumably about 20.9MHz if you have left it at its default speed.
With no prescaler this gives a resolution of 48ns and a maximum delay of about 3.125ms.
Setting the maximum prescaler (x128) gives a resolution of 6.14us and a maximum count of 400ms (if an output is toggled at each overflow it generates about 1.25Hz).

Based on the interval that you want (between 48ns and 400ms in the case of this clock speed) you can calculate the pre-scaler and remainder accordingly and program these into the SC and MOD registers to match.

You can also check the uTasker open source project at https://github.com/uTasker/uTasker-Kinetis to see its single-shot and periodic TPM interface allowing single short or periodic interrupts or DMA transfers on the KL25 (contains also Keil uVision project support).
It allows passing the delay/period in ms or us and calculates the pre-scaler and modulo value based on this and the clock used:

static __callback_interrupt void timer_int(void)
{
    TOGGLE_TEST_OUTPUT();
}

static void fnConfigure_Timer(void)
{
    static TIMER_INTERRUPT_SETUP timer_setup = {0};                      // interrupt configuration parameters
    timer_setup.int_type = TIMER_INTERRUPT;
    timer_setup.int_priority = PRIORITY_TIMERS;                          // interrupt priority
    timer_setup.int_handler = timer_int;
    timer_setup.timer_reference = 0;                                     // timer 0 (TPM 0 for KL25)
    timer_setup.timer_value = TIMER_US_DELAY(100000);                    // delay of 100ms
    fnConfigureInterrupt((void *)&timer_setup);                          // configure timer interrupt for timer test
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

It also simulates the timer operation so that complete projects can be developed, tested and debugger in visual studio.

Regards

Mark

Complete Kinetis solutions for professional needs, training and support:http://www.utasker.com/kinetis.html
Kinetis KL25:
- http://www.utasker.com/kinetis/FRDM-KL25Z.html
- http://www.utasker.com/kinetis/TWR-KL25Z48M.html
uTasker: supporting >1'000 registered Kinetis users get products faster and cheaper to market

0 Kudos

882 Views
kowshik700
Contributor I

Hello Mark,

Thanks for that quick reply sir. But this is not what I was expecting, the code you shared to me ain't seeming like a bare metal code. I guess it is written in some HAL software like MCUexpresso or so. I want correction of my code, the one you shared me is not so very useful and most the theory part you told me is already known and that is how I have been programming the General Purpose timers for my self. Please help me out with some more information sir.

Thanks in advance.

0 Kudos

882 Views
mjbcswitzerland
Specialist V

Hi

I pointed you to the complete source (which is "bare metal" code - all HAL will have bare-metal code somewhere beneath it but developers can work faster and more efficiently using the HAL). It contains a file called "kinetis_FLEXTIMER.h" which contains the full details.
Note that MCUxpresso is an IDE and not a library. There is a SDK which is sometimes used together with it that includes libraries and HAL. The uTasker project is an alternative that has more powerful and higher abstraction interfaces and peripheral simulation for those that need to quickly complete product developments rather than invest time in too much low level details (although its simulator allow also faster learning of HW details if needed too).

The "bare-metal" part equates to (approx.), but it is best to see the real code for full details.

    register int iPrescaler = 0;
    register unsigned long ulDelay = (((ptrTimerSetup->timer_value) * (MCGFFCLK / 1000)) / 1000;
    FLEX_TIMER_MODULE *ptrFlexTimer; = (FLEX_TIMER_MODULE *)FTM_BLOCK_0;
    POWER_UP_ATOMIC(6, FTM0);                                    // ensure that the FlexTimer module is powered up
    while (ulDelay > 0xffff) {                                   // calculate the optimal prescaler setting
        if (iPrescaler >= 7) {
            ulDelay = 0xffff;                                    // set maximum delay
            break;
        }
        iPrescaler++;
        ulDelay /= 2;
    }
    fnEnterInterrupt(irq_FTM0_ID, ptrTimerSetup->int_priority, _flexTimerInterrupt[iTimerReference]); // enter flex timer interrupt handler
    ptrFlexTimer->FTM_MOD = ulDelay;                             // set upper count value
    ptrFlexTimer->FTM_SC = ((unsigned short)iPrescaler | FTM_SC_CLKS_SYS | FTM_SC_TOIE);

Regards

Mark

Complete Kinetis solutions for professional needs, training and support:http://www.utasker.com/kinetis.html
uTasker: supporting >1'000 registered Kinetis users get products faster and cheaper to market

0 Kudos