Using MPLAB® Harmony v2 Static Drivers to Control Timers

 Summary

This page illustrates the steps needed to configure a timer and associated interrupt vector using static drive function calls. When a timer is configured to use a static driver, a unique interrupt vector is created for the timer.
This example uses a Timer1 generated interrupt.

Steps demonstrated on this page include:

  1. Using MPLAB® Harmony Configurator (MHC) to create the project structure with a static driver for Timer1.
  2. Verifying the function DRV_TMR0_Initialize() establishes Timer1's operating parameters.
  3. Implementing the Interrupt Service Routine (ISR) in the file system_interrupt.c.
  4. Modifying the function APP_Init() to enable the MCU to accept Timer1 interrupts.
  5. Modifying the main application program, APP_Tasks() to start Timer1.

Using MHC to Create a Project

Under the Driver section check the Use Timer Driver? box. Ensure a STATIC timer driver is used. When STATIC is selected you will have the option of configuring the timer settings as well as the interrupt priority levels.

static-setup2.png

Under the System Service section of the MHC, you should observe the Clock and Ports system services have been selected by default. Leave the Timer system services unchecked.

Below is the project directory and file structure generated by the MHC.
The illustration shows the source file (or file directory) of the functions needed to be modified in order to use a static timer driver.

project-file-drv.png

Configuring the Timer

  • The code for the timer's configuration parameters and interrupt levels are generated by the MHC and placed in the function DRV_TMR_Initialize.
  • For a system using a static driver, the driver initialization function is placed in the file drv-tmr-static.c.
  • The drv_tmr_static.c file is placed within the system configuration directory structure as shown in the picture below.

drv-tmr-static.c

void DRV_TMR0_Initialize(void)
{
/* Initialize Timer Instance0 */
/* Disable Timer */

PLIB_TMR_Stop(TMR_ID_1);
/* Select clock source */
PLIB_TMR_ClockSourceSelect(TMR_ID_1,
TMR_CLOCK_SOURCE_PERIPHERAL_CLOCK);

/* Select prescalar value */
PLIB_TMR_PrescaleSelect(TMR_ID_1, TMR_PRESCALE_VALUE_256);
/* Enable 16 bit mode */
PLIB_TMR_Mode16BitEnable(TMR_ID_1);
/* Clear counter */
PLIB_TMR_Counter16BitClear(TMR_ID_1);
h/*Set period */
PLIB_TMR_Period16BitSet(TMR_ID_1, 0);

/* Setup Interrupt */
PLIB_INT_SourceEnable(INT_ID_0, INT_SOURCE_TIMER_1);
PLIB_INT_VectorPrioritySet(INT_ID_0, INT_VECTOR_T1,
INT_PRIORITY_LEVEL5);
PLIB_INT_VectorSubPrioritySet(INT_ID_0, INT_VECTOR_T1,
INT_SUBPRIORITY_LEVEL0);

}

  • You should examine DRV_TMR_Initialize() to ensure the timer is configured to your specifications.
  • During the applications start-up phase, DRV_TMR_Initialize() is called by the system initialization function SYS_Initialize().
  • Static driver functions are implemented using Peripheral Libraries.

Adding Code to the Interrupt Service Routine

  • The MHC will generate separate interrupt vectors for each driver instance defined.
  • The drivers will be placed in system_interrupt.c.
  • Each interrupt vector will contain code which clears the interrupt flag (PLIB_INt_Sourceflagclear(..)).
  • You are responsible for adding code to execute the task required of the ISR. In this example, you are asked to enter your own ISR functionality.

system-interrupt.c


void __ISR(_TIMER_1_VECTOR, ipl5) _IntHandlerDrvTmrInstance0(void)
{
// User-Written ISR code goes here!
PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_TIMER_1);
}


Enabling Timer Interrupts

  • The function to initialize the application, APP_Initialize() is located in app.c.
  • In this example, a line of code was added to enable interrupts from Timer1.

app.c


void APP_Initialize (void)
{
appData.state = APP_STATE_INIT;
PLIB_INT_SourceEnable(INT_ID_0, INT_SOURCE_TIMER_1);

}


Starting the Timers

  • The main application function, APP_Tasks(), is located in app.c.
  • In this example, during the initial state of the application (APP_STATE_INIT), the timer is started.

app.c


void APP_Tasks (void)
{
switch ( appData.state )
{
case APP_STATE_INIT:
{
DRV_TMR0_Start(); // Start the Timers
break;
}
}
}


 Learn More

 
Example Code and Projects
Learn more >
 
Harmony Timer System Services Tutorial
Learn more >
 
Harmony Timer Driver Tutorial
Learn more >
© 2024 Microchip Technology, Inc.
Notice: ARM and Cortex are the registered trademarks of ARM Limited in the EU and other countries.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.