A Circular Reference

Adventures of a vagabond electron.

A Simple Embedded Timer Pattern

| Comments

Introduction

One of the first things I do when I’m programming a new Microcontroller is to set up a timer for the system. Once you have the timer registers properly configured, the next problem is to measure time intervals, and worrying about overflows. The following pattern is the most elegant way of measuring timer intervals without giving you a headache that I have ever seen, and I reuse it all the time!

Problem

Need a method of measuring time intervals for all kinds of application modules. Simple time stamp difference does not work if the timer overflows.

Prerequisite

You have configured your (hardware) timer to generate a periodic interrupt every X seconds (or milli seconds or whatever). Choose the tick so that it provides at least the smallest resolution you need for your system.

Solution

  1. Inside the timer interrupt, increment a unsigned global variable, let’s call it FreeRunningCounter.

  2. To measure time difference, simply take a Time Stamp of the FreeRunningCounter at the start of the activity. The difference between the TimeStamp and the current FreeRunningCounter modulo the width of the hardware timer is the time elapsed. This will work so long as the measured period is less than or equal to the full range of FreeRunningCounter.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
UINT32 FreeRunningCounter;

void Timer_ISR(void){
FreeRunningCounter++; // In the ISR, just increment the counter
}

UINT32 GetTimeStamp(void){
// Achtung: If the word length of the variable FreeRunningCounter is greater than the data bus width of the processor,
// you should disable the timer interrupt before returning the timestamp, since the ISR could interrupt the read of FreeRunningCounter
// and end up modifying bytes of FreeRunningCounter while you are reading it.
#if THIS_IS_AN_8BIT_MACHINE
UINT32 time;
DisableTimerInt();
time = FreeRunningCounter;
EnableTimerInt();
return (time);
#elif THIS_IS_AN_32BIT_MACHINE
return(FreeRunningCounter);
#endif
}

// Elsewhere in the project
UINT32 timeStamp = GetTimeStamp(); // At some time take a snapshot
// ....... run a lot of code here
deltaT = (GetTimeStamp() - timeStamp) & 0xFFFFFFFF; // Gives you the time difference without overflow 

Comments