Millis - Timer based functions

Introduction:

The millis() library provides a simple, portable timing method for applications and libraries. It is supported on both AVR and PIC microcontrollers, and works by exposing three user-interrupt "hooks" that let user code run as part of the library’s own timer interrupt handler.

The three hooks are:

  1. User_Int_sec — generates a user interrupt every second.
  2. User_Int_ms — generates a user interrupt every millisecond.
  3. User_Int_XmS — generates a user interrupt every user-specified period, expressed in milliseconds.

Each is covered below, with a worked example.

Command Availability:

Available on all AVR and PIC microcontrollers, via #include "millis.h".

1. Usage — User_Int_sec

Define User_Int_sec to name the method called once a second:

    #Define  User_Int_Sec  MyTimerInterrupt
    Init_Millis()

MyTimerInterrupt is called every second once Init_Millis() starts the library’s timer.

2. Usage — User_Int_ms

Define User_Int_ms to name the method called every millisecond:

    #Define  User_Int_ms    MyTimerInterrupt
    Init_Millis()

MyTimerInterrupt can be a subroutine, function, macro, or inline code, but it must be short, since it runs inside the millis() library’s own interrupt handler.

Example for PIC:

A "Blink" example, using a macro as the hook target (the hook name does not have to be MyTimerInterrupt):

    #chip 16f18855
    #option Explicit
    #include "millis.h"

    #Define  User_Int_mS    Blink(MyLED, 250)          ' <<< the hook this page documents
    Init_Millis()

    #define MyLED porta.2
    dir MyLED out

    do
      ' main loop is empty but it is required to
      ' prevent the device performing a Sleep call on end
    loop

    end

    Macro Blink(Pin, Period)
      dim  BlinkX as word
      BlinkX += 1
      if BlinkX >= Period then
         BlinkX = 0
         Pin = !Pin
      end if
    end macro

Key line: #Define User_Int_mS Blink(MyLED, 250) — registers Blink(MyLED, 250) as the code the millis() library runs from inside its own millisecond interrupt, without the user program managing a timer interrupt directly.

Tested on the Microchip Xpress Demo Board; unlike GCBASIC’s hardware millis() support on other libraries, this hook-based approach is fully portable.

Porting to AVR:

To move the same example to an Arduino UNO board, change #chip 16f18855 to #chip mega328p,16, and #define MyLED porta.2 to #define MyLED portb.5:

    #chip mega328p,16
    #option Explicit
    #include "millis.h"

    #Define  User_Int_mS    Blink(MyLED, 250)
    Init_Millis()

    #define MyLED portb.5
    dir MyLED out

    do
      ' main loop is empty but it is required to
      ' prevent the device performing a Sleep call on end
    loop

    end

    Macro Blink(Pin, Period)
      dim  BlinkX as word
      BlinkX += 1
      if BlinkX >= Period then
         BlinkX = 0
         Pin = !Pin
      end if
    end macro

3. Usage — User_Int_XmS

Define User_Int_XmS to call a task at a specified period: type, period, task.

type is Byte, Word, Long, or any valid variable; period is the number of milliseconds between calls to the hook; task is the macro, sub, or inline code run when the hook fires:

    #chip 16f18855
    #option Explicit
    #include "millis.h"

    #define MyLED porta.2
    dir MyLED out

    #Define  User_Int_XmS    Word, 500, MyLED = !MyLED          ' <<< calls the hook every 500 ms
    Init_Millis()

    do
      ' main loop is empty as everything happens within
      ' the user hook. It is required, however, to
      ' prevent the device going to Sleep.
    loop

    end

Key line: #Define User_Int_XmS Word, 500, MyLED = !MyLED — toggles MyLED every 500 ms directly from the hook, with no code needed in the main loop at all.

See Also:

  • Timer Overview — the underlying hardware timers this library is built on
  • InitTimer0 — setting up a hardware timer manually, as an alternative to the millis() hooks