2.7 Timer Driver

2.7.1 Introduction

The MPLAB® Code Configurator (MCC) Timer Driver provides a portable API interface to assist a generic Timer interface that supports the MCC Melody Component concepts: configuration and firmware portability.

The Timer Driver will require a Peripheral LIBrary (PLIB) dependency, closely associated to aTimer hardware peripheral. On PIC® MCUs, the Timer Driver supports the following Timer PLIBs:

  • TMR0
  • TMR1/3/5
  • TMR2/4/6
  • Universal Timer (TU)

Timers are often used in timing and scheduling applications.

2.7.2 Required header files:

#include "mcc_generated_files/timer/tmr[X].h"

or

#include "mcc_generated_files/timer/tu16[X].h"

Note: Replace [X] with the selected instance of the Timer or TU module.

2.7.3 How to use the Timer Driver

The Timer driver generates a portable API interface. For examples of how to use the interface, refer to the examples linked below. Click the links to view the code snippets associated with each example:

2.7.4 Timer Driver

2.7.4.1 Module Documentation

2.7.4.1.1 Timer Driver

The Timer driver is an 8-bit, 16-bit or 32-bit timer that can operate as a free-running interval timer using PIC®, dsPIC® and AVR® microcontrollers (MCUs).

Module description

The Timer driver is an 8-bit, 16-bit or 32-bit timer that can operate as a free-running interval timer using PIC®, dsPIC® and AVR® microcontrollers (MCUs).

Data structures
  • struct TIMER_INTERFACE

    Structure containing the function pointers of the Timer driver.

Definitions
Functions
  • void TMRx_Initialize (void)

    Initializes the Timer0 (TMRx) module. This routine must be called before any other TMRx routines.

  • void TMRx_Deinitialize (void)

    Deinitializes the TMRx module.

  • void TMRx_Start (void)

    Starts the TMRx timer.

  • void TMRx_Stop (void)

    Stops the TMRx timer.

  • uint32_t TMRx_CounterGet (void)

    Returns the current counter value.

  • void TMRx_CounterSet (uint32_t counterValue)

    Sets the counter value.

  • void TMRx_PeriodSet (uint32_t periodCount)

    Sets the period count value.

  • uint32_t TMRx_PeriodGet (void)

    Returns the current period value.

  • uint32_t TMRx_MaxCountGet (void)

    Returns the maximum count value.

  • void TMRx_ISR (void)

    Interrupt Service Routine (ISR) for the TMRx overflow interrupt.

  • void TMRx_OverflowCallbackRegister (void(*CallbackHandler)(void))

    Registers a callback function for the TMRx overflow event.

  • void TMRx_Tasks (void)

    Performs tasks to be executed during the TMRx overflow event.

Definition Documentation
TIMERx_CLOCK_FREQ

#define TIMERx_CLOCK_FREQ TMR0_CLOCK_FREQ

Defines the Custom Name for the TMRx_CLOCK_FREQ.

TimerX_CounterGet

#define TimerX_CounterGet TMR0_CounterGet

Defines the Custom Name for the TMRx_CounterGet API.

TimerX_CounterSet

#define TimerX_CounterSet TMR0_CounterSet

Defines the Custom Name for the TMRx_CounterSet API.

TimerX_Deinitialize

#define TimerX_Deinitialize TMR0_Deinitialize

Defines the Custom Name for the TMRx_Deinitialize API.

TimerX_Initialize

#define Timer0_Initialize TMR0_Initialize

Defines the Custom Name for the TMRx_Initialize API.

TimerX_ISR

#define TimerX_ISR TMR0_ISR

Defines the Custom Name for the TMRx_ISR API.

TIMERx_MAX_COUNT

#define TIMERx_MAX_COUNT TMR0_MAX_COUNT

Defines the Custom Name for the TMRx_MAX_COUNT.

TimerX_MaxCountGet

#define TimerX_MaxCountGet TMR0_MaxCountGet

Defines the Custom Name for the TMRX_MaxCountGet API.

TimerX_OverflowCallbackRegister

#define TimerX_OverflowCallbackRegister TMR0_OverflowCallbackRegister

Defines the Custom Name for the TMRx_OverflowCallbackRegister API.

TimerX_PeriodGet

#define TimerX_PeriodGet TMR0_PeriodGet

Defines the Custom Name for the TMRx_PeriodGet API.

TimerX_PeriodSet

#define TimerX_PeriodSet TMR0_PeriodSet

Defines the Custom Name for the TMRx_PeriodSet API.

TimerX_Start

#define TimerX_Start TMR0_Start

Defines the Custom Name for the TMRx_Start API.

TimerX_Stop

#define TimerX_Stop TMR0_Stop

Defines the Custom Name for the TMRx_Stop API.

TimerX_Tasks

#define TimerX_Tasks TMR0_Tasks

Defines the Custom Name for the TMRx_Tasks API.

TIMER_INTERRUPT_PRIORITY_SUPPORT

#define TIMER_INTERRUPT_PRIORITY_SUPPORT 0

The InterruptPrioritySet API is not supported.

TIMER_PERIODCOUNTSET_API_SUPPORT

#define TIMER_PERIODCOUNTSET_API_SUPPORT 0

Defines the deprecated SCCPx_Timer_PeriodCountSet or TMRx_PeriodCountSet API. Set it to 1 for backward compatibility for 16-bit MCUs only.

TMRx_CLOCK_FREQ

#define TMRx_CLOCK_FREQ (32000000UL)

Defines the timer prescaled clock frequency in hertz.

TMRx_MAX_COUNT

#define TMRx_MAX_COUNT (65535U)

Defines the maximum count value of the timer.

MISRA C:2012 Deviation Advisory: misra-c2012-2.5  

Justification: MCC Melody drivers provide macros that can be added to an application. It depends on the application whether a macro is used or not.

Function Documentation
TMRx_CounterGet()

uint32_t TMRx_CounterGet (void )

Returns the current counter value.

Precondition:

Initialize TMRx with TMRx_Initialize() before calling this API.

Parameters:
None.
Returns:

Counter value from the TMRx register

TMRx_CounterSet()

void TMRx_CounterSet (uint32_t counterValue)

Sets the counter value.

Precondition:

Initialize TMR0 with TMRx_Initialize() before calling this API.

Parameters:
counterValue

- Counter value to be written to the TMRx register

Returns:

None.

TMRx_Deinitialize()

void TMRx_Deinitialize (void )

Deinitializes the TMRx module.

Parameters:
None.
Returns:

None.

TMRx_Initialize()

void TMRx_Initialize (void )

Initializes the TimerX (TMRx) module. This routine must be called before any other TMRx routines.

Parameters:
None.
Returns:

None.

TMRx_ISR()

void TMRx_ISR (void )

Interrupt Service Routine (ISR) for the TMRx overflow interrupt.

Parameters:
None.
Returns:

None.

TMRx_MaxCountGet()

uint32_t TMRx_MaxCountGet (void )

Returns the maximum count value.

Parameters:
None.
Returns:

Maximum count value

TMRx_OverflowCallbackRegister()

void TMRx_OverflowCallbackRegister (void(*)(void) CallbackHandler)

Registers a callback function for the TMR0 overflow event.

Parameters:
CallbackHandler

- Address of the custom callback function

Returns:

None.

Registers a callback function for the TMR0 overflow event.

Parameters:
CallbackHandler

- Address to the custom callback function

Returns:

None.

TMRx_PeriodGet()

uint32_t TMRx_PeriodGet (void )

Returns the current period value.

Precondition:

Initialize TMRx with TMRx_Initialize() before calling this API.

Parameters:
None.
Returns:

Period count value

TMRx_PeriodSet()

void TMRx_PeriodSet (uint32_t periodCount)

Sets the period count value.

Precondition:

Initialize TMRx with TMRx_Initialize() before calling this API.

Parameters:
periodCount

- Period count value to be written to the TMR0 register

Returns:

None.

TMRx_Start()

void TMR0_Start (void )

Starts the TMR0 timer.

Precondition:

Initialize TMRx with TMRx_Initialize() before calling this API.

Parameters:
None.
Returns:

None.

TMRx_Stop()

void TMRx_Stop (void )

Stops the TMRx timer.

Precondition:

Initialize TMRx with TMRx_Initialize() before calling this API.

Parameters:
None.
Returns:

None.

TMRx_Tasks()

void TMRx_Tasks (void )

Performs tasks to be executed during the TMRx overflow event.

Parameters:
None.
Returns:

None.

2.7.4.2 Data Structure Documentation

2.7.4.2.1 TIMER_INTERFACE Struct Reference

Structure containing the function pointers of the Timer driver.

Detailed Description

Structure containing the function pointers of the Timer driver.

Declares an instance of TIMER_INTERFACE for the TMR0 module.

#include <timer_interface.h>

Data Fields
  • void(* Initialize )(void)

    Pointer to MCCPx_Timer_Initialize, SCCPx_Timer_Initialize or TMRx_Initialize (e.g., SCCP1_Timer_Initialize or TMR1_Initialize).

  • void(* Deinitialize )(void)

    Pointer to MCCPx_Timer_Deinitialize, SCCPx_Timer_Deinitialize or TMRx_Deinitialize (e.g., SCCP1_Timer_Deinitialize or TMR1_Deinitialize).

  • void(* Start )(void)

    Pointer to MCCPx_Timer_Start, SCCPx_Timer_Start or TMRx_Start (e.g., SCCP1_Timer_Start or TMR1_Start).

  • void(* Stop )(void)

    Pointer to MCCPx_Timer_Stop, SCCPx_Timer_Stop or TMRx_Stop (e.g., SCCP1_Timer_Stop or TMR1_Stop).

  • void(* PeriodSet )(uint32_t count)

    Pointer to MCCPx_Timer_PeriodSet, SCCPx_Timer_PeriodSet or TMRx_PeriodSet (e.g., SCCP1_Timer_PeriodSet or TMR1_PeriodSet).

  • uint32_t(* PeriodGet )(void)

    Pointer to MCCPx_Timer_PeriodGet, SCCPx_Timer_PeriodGet or TMRx_PeriodGet (e.g., SCCP1_Timer_PeriodGet or TMR1_PeriodGet).

  • uint32_t(* CounterGet )(void)

    Pointer to MCCPx_Timer_CounterGet, SCCPx_Timer_CounterGet or TMRx_CounterGet (e.g., SCCP1_Timer_CounterGet or TMR1_CounterGet).

  • void(* CounterSet )(uint32_t count)

    Pointer to MCCPx_Timer_CounterSet, SCCPx_Timer_CounterSet or TMRx_CounterSet (e.g., SCCP1_Timer_CounterSet or TMR1_CounterSet).

  • uint32_t(* MaxCountGet )(void)

    Pointer to MCCPx_Timer_MaxCountGet, SCCPx_Timer_MaxCountGet or TMRx_MaxCountGet (e.g., SCCP1_Timer_MaxCountGet or TMR1_MaxCountGet).

  • void(* TimeoutCallbackRegister )(void(*CallbackHandler)(void))

    Pointer to MCCPx_TimeoutCallbackRegister, SCCPx_TimeoutCallbackRegister or TMRx_TimeoutCallbackRegister (e.g., SCCP1_TimeoutCallbackRegister or TMR1_TimeoutCallbackRegister).

  • void(* Tasks )(void)

    Pointer to MCCPx_Timer_Tasks, SCCPx_Timer_Tasks or TMRx_Tasks (e.g., SCCP1_Timer_Tasks or TMR1_Tasks , supported only in Polling mode).

Field Documentation

The documentation for this struct was generated from the following file:

source/

timer_interface.h

CounterGet

uint32_t(* CounterGet) (void)

Pointer to MCCPx_Timer_CounterGet, SCCPx_Timer_CounterGet or TMRx_CounterGet (e.g., SCCP1_Timer_CounterGet or TMR1_CounterGet).

CounterSet

void(* CounterSet) (uint32_t count)

Pointer to MCCPx_Timer_CounterSet, SCCPx_Timer_CounterSet or TMRx_CounterSet (e.g., SCCP1_Timer_CounterSet or TMR1_CounterSet).

Deinitialize

void(* Deinitialize) (void)

Pointer to MCCPx_Timer_Deinitialize, SCCPx_Timer_Deinitialize or TMRx_Deinitialize (e.g., SCCP1_Timer_Deinitialize or TMR1_Deinitialize).

Initialize

void(* Initialize) (void)

Pointer to MCCPx_Timer_Initialize, SCCPx_Timer_Initialize or TMRx_Initialize (e.g., SCCP1_Timer_Initialize or TMR1_Initialize).

MaxCountGet

uint32_t(* MaxCountGet) (void)

Pointer to MCCPx_Timer_MaxCountGet, SCCPx_Timer_MaxCountGet or TMRx_MaxCountGet (e.g., SCCP1_Timer_MaxCountGet or TMR1_MaxCountGet).

PeriodGet

uint32_t(* PeriodGet) (void)

Pointer to MCCPx_Timer_PeriodGet, SCCPx_Timer_PeriodGet or TMRx_PeriodGet (e.g., SCCP1_Timer_PeriodGet or TMR1_PeriodGet).

PeriodSet

void(* PeriodSet) (uint32_t count)

Pointer to MCCPx_Timer_PeriodSet, SCCPx_Timer_PeriodSet or TMRx_PeriodSet (e.g., SCCP1_Timer_PeriodSet or TMR1_PeriodSet).

Start

void(* Start) (void)

Pointer to MCCPx_Timer_Start, SCCPx_Timer_Start or TMRx_Start (e.g., SCCP1_Timer_Start or TMR1_Start).

Stop

void(* Stop) (void)

Pointer to MCCPx_Timer_Stop, SCCPx_Timer_Stop or TMRx_Stop (e.g., SCCP1_Timer_Stop or TMR1_Stop).

Tasks

void(* Tasks) (void)

Pointer to MCCPx_Timer_Tasks, SCCPx_Timer_Tasks or TMRx_Tasks (e.g., SCCP1_Timer_Tasks or TMR1_Tasks , supported only in Polling mode).

TimeoutCallbackRegister

void(* TimeoutCallbackRegister) (void(*CallbackHandler)(void))

Pointer to MCCPx_TimeoutCallbackRegister, SCCPx_TimeoutCallbackRegister or TMRx_TimeoutCallbackRegister (e.g., SCCP1_TimeoutCallbackRegister or TMR1_TimeoutCallbackRegister).

2.7.4.3 Module Examples

2.7.4.3.1 Timer Driver Examples

40 ms/80 ms Timer Period Change When Switch Is Pressed

This use case sets up a project which changes the time-out period between 40 ms and 80 ms, when a switch is pressed.

System Configuration
  • System>Clock Control:
    • Clock Source: HFINTOSC

    • HF Internal Clock: 64 MHz

  • System>Pins:
    • Pin Grid View: Select LED pin as output (Check the schematic for your board)

    • Pins: Rename Custom Name to "LED"

    • Pin Grid View: Select SWITCH pin as input (check the schematic for your board)

    • Pins: Rename Custom Name to "SW"

    • Enable Weak Pullup if needed

Timer Configuration
  • Drivers>Timer:
    • Timer PLIB Selector: TMR0

    • Timer Enable: False

    • Interrupt Driven: True

    • Requested Period: 100 ms

After configuring the components as described above, click 'Generate' to generate the code. Then add the following code snippets to your application:

#include "mcc_generated_files/system/system.h"

/*
 * Development Board: PIC18F57Q43 Curiosity Nano Board
 * MCC Configuration:
 *     System module: HFINTOSC (64 MHz)
 *     Timer module: Timer PLIB Selector - TMR0, Timer Enable - False, Interrupt Driven - True, Requested Timer Period - 100 ms
 *     TMR0 module: Timer_PeriodSet() API Range - [2 us - 131.072 ms] (read-only)
 *     Pins module: RF3 - GPIO Output, CustomName - LED
 *                  RB4 - GPIO Input, CustomName - SW, Weak Pull Up - Enable 
 */

#define SW_PRESSED 0U          // Switch - Active Low
#define SW_NOT_PRESSED 1U 
#define DEBONCE_DELAY_MS 20U      // Depends on hardware

#define MS_TO_TICKS(ms) (((TMR0_CLOCK_FREQ * (ms)) / 1000UL) - 1UL)
#define LED_40_MS (MS_TO_TICKS(40UL))           
#define LED_80_MS (MS_TO_TICKS(80UL))

static const struct TIMER_INTERFACE *Timer = &Timer0;

bool SW_StateGet(void)
{
    bool status = SW_NOT_PRESSED;
    if(SW_PRESSED == SW_GetValue())
    {
        __delay_ms(DEBONCE_DELAY_MS);
        if(SW_PRESSED == SW_GetValue())
        {
            status = SW_PRESSED;
        }        
    }
    return status;
}

void Timer_FrequencyChange(void)
{
    static volatile bool changePeriod = false;
    Timer->Stop();
    
    uint32_t maxCount = Timer->MaxCountGet();
    uint32_t newPeriod = changePeriod ? LED_40_MS:LED_80_MS;
    
    if(maxCount > newPeriod)
    {      
        Timer->PeriodSet(newPeriod);
    }
    else
    {
        // Invalid period
    }
    changePeriod = !changePeriod;
    Timer->Start(); 
}

void Timer_Callback(void)
{
    LED_Toggle();
}

int main(void)
{
    SYSTEM_Initialize();

    Timer->PeriodSet(LED_40_MS);
    Timer->TimeoutCallbackRegister(Timer_Callback);
    Timer->Start();    
  
    // Enable the Global Interrupts 
    INTERRUPT_GlobalInterruptEnable(); 
    
    while(1)
    {
        if(SW_PRESSED == SW_StateGet())
        {
            Timer_FrequencyChange();
        }
    }    
}
A Simple Task Scheduler That Executes Two Different Tasks At Different Intervals Using Timer Interrupt

This use case sets up a project which executes two different tasks at different intervals using a timer interrupt.

System Configuration
  • System>Clock Control:
    • Clock Source: HFINTOSC

    • HF Internal Clock: 64 MHz

  • System>Pins:
    • Pin Grid View: Select LED1 pin as output (Check the schematic for your board)

    • Pins: Rename Custom Name to "LED1"

    • Pin Grid View: Select LED2 pin as output (Check the schematic for your board)

    • Pins: Rename Custom Name to "LED2"

Timer Configuration
  • Drivers>Timer:
    • Timer PLIB Selector: TMR0

    • Timer Enable: False

    • Interrupt Driven: True

    • Requested Period: 1 ms

After configuring the components as described above, click 'Generate' to generate the code. Then add the following code snippets to your application:

#include "mcc_generated_files/system/system.h"

/*
 * Development Board: PIC18F57Q43 Curiosity Nano Board
 * MCC Configuration:
 *     System module: HFINTOSC (64 MHz)
 *     Timer module: Timer PLIB Selector - TMR0, Timer Enable - False, Interrupt Driven - True, Requested Timer Period - 1 ms
 *     Pins module: RF2, RF3 - GPIO Output, CustomName - RF2->LED1, RF3->LED2 
 */

static void Task_A_2ms(void)
{
    LED1_SetHigh();
    NOP();
    NOP();
    LED1_SetLow();
    
    // Add your code here. E.g., LED Toggle
}
static void Task_B_5ms(void)
{
    LED2_SetHigh();
    NOP();
    NOP();
    LED2_SetLow();  
    
    // Add your code here. E.g., Read Sensor
}
static void Tasks_Scheduler(void)
{
    static volatile uint8_t oneMs_tickCounter =  0;
    
    oneMs_tickCounter++;
            
    if((oneMs_tickCounter % 2U) == 0U)
    {
        Task_A_2ms();    // Run at 2 ms, 4 ms, 6 ms, 8 ms, and 10 ms.
    }
    
    if((oneMs_tickCounter % 5U) == 0U)
    {
        Task_B_5ms();    // Run at 5 ms and 10 ms.
    }
    if(oneMs_tickCounter == 10U)
    {
        oneMs_tickCounter = 0;
    }
}

int main(void)
{
    const struct TIMER_INTERFACE *Timer = &Timer0;

    SYSTEM_Initialize();
 
    Timer->TimeoutCallbackRegister(Tasks_Scheduler);
    Timer->Start();
    
    // Enable the Global Interrupts 
    INTERRUPT_GlobalInterruptEnable(); 

    while(1)
    {
    }    
}
4 ms/8 ms Timer Period Change During Each Interrupt Event

This use case configures the Timer module to use the TMR0 Peripheral Library (PLIB) to generate an overflow interrupt. The period of a timer is changed at run time during each interrupt event.

System Configuration
  • System>Clock Control:
    • Clock Source: HFINTOSC

    • HF Internal Clock: 64 MHz

  • System>Pins:
    • Pin Grid View: Select LED pin as output (Check the schematic for your board)

    • Pins: Rename Custom Name to "LED"

Timer Configuration
  • Drivers>Timer:
    • Timer PLIB Selector: TMR0

    • Timer Enable: False

    • Interrupt Driven: True

    • Requested Period: 10 ms

After configuring the components as described above, click 'Generate' to generate the code. Then add the following code snippets to your application:

#include "mcc_generated_files/system/system.h"

/*
* Development Board: PIC18F57Q43 Curiosity Nano Board
* MCC Configuration:
*     Clock Control: HFINTOSC (64 MHz)
*     Timer module: Timer PLIB Selector - TMR0, Timer Enable - False, Interrupt Driven - True, Requested Timer Period - 10 ms 
*     TMR0 module: Timer_PeriodSet() API Range - [250 ns - 16.384 ms] (read-only)
*     Pins module: RF3 - GPIO Output, CustomName - LED 
*/
 
#define TIMER_TICK_FREQ TMR0_CLOCK_FREQ
#define MS_TO_TICKS(ms) (((TIMER_TICK_FREQ * (ms)) / 1000UL) - 1UL)
#define LED_4_MS MS_TO_TICKS(4UL)        // Set the period to be within the PeriodSet API range
#define LED_8_MS MS_TO_TICKS(8UL)

static const struct TIMER_INTERFACE *Timer = &Timer0;
static void Timer_PeriodChange(void)
{ 
    static volatile bool changePeriod = false;
    LED_Toggle();
    Timer->Stop();
    
    uint32_t maxCount = Timer->MaxCountGet();
    uint32_t newPeriod = changePeriod ? LED_4_MS : LED_8_MS;
    
    if(maxCount > newPeriod)
    {     
        Timer->PeriodSet(newPeriod);
    }
    else
    {
        // Invalid period       
    }
    
    changePeriod = !changePeriod;
    Timer->Start();
}

int main(void)
{
    SYSTEM_Initialize();
    
    Timer->PeriodSet(LED_4_MS);
    Timer->TimeoutCallbackRegister(Timer_PeriodChange);
    Timer->Start();
    
    // Enable the Global Interrupts 
    INTERRUPT_GlobalInterruptEnable(); 
    
    while(1)
    {
    }    
}
500 ms Timer Period in Non-Interrupt Mode

This use case configures the Timer module to use the TMR0 PLIB to generate a specified timer period in Non-Interrupt mode.

System Configuration
  • System>Clock Control:
    • Clock Source: HFINTOSC

    • HF Internal Clock: 64 MHz

  • System>Pins:
    • Pin Grid View: Select LED pin as output (Check the schematic for your board)

    • Pins: Rename Custom Name to "LED"

Timer Configuration
  • Drivers>Timer:
    • Timer PLIB Selector: TMR0

    • Timer Enable: False

    • Interrupt Driven: False

    • Requested Period: 500 ms

After configuring the components as described above, click 'Generate' to generate the code. Then add the following code snippets to your application:

#include "mcc_generated_files/system/system.h"

/*
* Development Board: PIC18F57Q43 Curiosity Nano Board
* MCC Configuration:
*     Clock Control: HFINTOSC (64 MHz)
*     Timer module: Timer PLIB Selector - TMR0, Timer Enable - False, Interrupt Driven - False, Requested Timer Period - 500 ms 
*     Pins module: RF3 - GPIO Output, CustomName - LED 
*/

static void Timer_Callback(void)
{
    LED_Toggle();   
}

int main(void)
{
    SYSTEM_Initialize();

    Timer0.TimeoutCallbackRegister(Timer_Callback);
    Timer0.Start();
    while(1)
    {
        Timer0.Tasks();
    }    
}

2.7.4.4 File Documentation

2.7.4.4.1 source/timer_interface.h File Reference

#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
Data structures
  • struct TIMER_INTERFACE

    Structure containing the function pointers of the Timer driver.

Detailed Description

TIMER Generated Driver Interface Header File